【转帖】系统软件工程师必备技能-进程内存的working set size(WSS)测量
系统软件工程师必备技能-进程内存的working set size(WSS)测量
How To Measure the Working Set Size on Linux|来源:内核月谈
概述
本文主要摘自brendangregg大神的blog:
http://www.brendangregg.com/blog/2018-01-17/measure-working-set-size.html
研究如何衡量一个特定业务程序的working set size。先不谈概念,让我们一起先思考一下为什么要研究WSS呢?举个例子来说,某些后台daemon为了性能,喜欢在程序在启动阶段就创建好各种fixed-size的内存池,且不支持动态grow/shrink,这些内存池的真实利用率如何?是否存在浪费?访问频率如何?读者可能会想到通过在内存池实现上做一些简单统计,不难得到程序的访问频率或者冷热内存页。那么如果是一个第三方程序呢?对测量的人来说是一个黑盒子,这种场景则只能尝试在操作系统层来考虑。本文从Linux的角度系统阐述了目前的常用手段,有什么缺陷以及一些优化手段。
作者
邓刚,马涛,Linux系统工程师,来自阿里云系统组。
本文中若有任何疏漏错误,有任何建议和意见,请回复内核月谈微信公众号,或通过gavin.dg at linux.alibaba.com>或者 tao.ma at linux.alibaba.com反馈。
阿里云系统团队,是由原淘宝内核组扩建而成,2013年淘宝内核组响应阿里巴巴集团的号召,整建制转入阿里云,开始为云计算底层系统构建完善的系统支持。 阿里云系统团队是由一群具有高度使命感和自我追求的内核开发人员组成,团队中的大多数人,都是活跃的社区内核开发人员。目前的工作领域主要涉及(但不限于) Linux内核的内存管理、文件系统、网络和内核维护构建,以及和内核相关联的用户态库和工具。如果你对我们的工作很感兴趣,欢迎加入我们,请将简历发送至 tao.ma at linux.alibaba.com或者 boyu.mt at alibaba-inc.com。
正文
Working Set Size(WSS)是指一个app保持正常运行所须的内存。比如一个应用在初始阶段申请了100G主存,在实际正常运行时每秒只需要50M,那么这里的50M就是一个WSS。评估WSS能干嘛呢?它可以用来进行内存容量规划并进行必要的内存扩容或者软件优化。这个问题并不新鲜而且非常重要,然而brendangregg却表示至今为止没有实际可用的有效工具(译者注:严重同意,而且在翻译这篇文章之前译者也开发了类似工具,在阿里巴巴内部使用)。有经验的读者可能会注意到Linux top命令的输出中,有两列分别是VIRT与RES,其中VIRT是进程使用的虚拟内存地址空间大小,而RES则是实际使用的物理内存(如果考虑共享映射等,则需要用到smaps proc文件的PSS或者top命令的SHARE,不过这两者对于理解WSS无益,故不在此展开)。比如,一个进程刚启动时通过私有匿名映射了(map_flags=MAP_PRIVATE | MAP_ANON)100G内存,然后实际只访问其中50G,那么VIRT=100G,RES=50G。那么问题来了,如何评估这50G内存的访存频率呢?是否存在明显的冷热区分呢?针对这个问题,brendangregg开发了两款基于Linux系统的小工具,下文将分别详细介绍。
Method 1: Referenced Page flag
这是基于Linux Kernel 2.6.22引入的一个特性:the ability to set and read the referenced page flag from user space, added for analyzing memory usage. brendangregg大神基于此实现了一个https://github.com/brendangregg/wss wss.pl工具,下面的案例在0.1s内存测量mysqld(PID=423)的WSS:
上面表示0.1秒内mysqld访问了28M物理内存(总内存403.66M)。为什么选取0.1s而不是更长?大神解释说这样短时间段内的测量可以帮助我们正确评估业务程序对CPU cache的使用(比如L1/L2/L3, TLB L1/L2等)。28M略大于CPU LLC的大小,所以cache并非工作得很完美。这个工具也支持累计模式,仅重置一次referenced flag然后以固定间隔持续采集,输出如下:
可以看到WSS在逐渐增加。其中各列的含义:
Est(s): 采集时刻;
RSS(MB):物理内存使用(MBytes);
PSS(MB):按共享映射的次数,均摊算出的物理内存使用量(MBytes);
Ref(MB):在Est(s)内,进程实际访问过的内存(MBytes)。
细心的读者可能会发现,数据中的Est并非恰好是整数秒。这里的原因是因为程序本身在重置referenced flag或者从proc接口读取都需要消耗一定的时间,而且随着进程使用的内存越多,开销越大。
这个小工具的原理什么呢?对x86 MMU架构有了解的读者应该知道PTE有一个bit为 accessed bit。它的特性是:一旦CPU访问了一个内存地址,那么该地址相应的PTE的accessed bit将会被置上。这是一个硬件特性,至于如果利用它则需要我们一起发挥想象力了。著名的linux mm 子系统里的LRU页框回收算法,在除了以软件的方式打tag之外,就依赖了该bit来区分页的冷热程度。这里多说一句,其实WSS这个小工具的目的是找出特定时间段内被访问过的页,而LRU则是找出最近一段时间段内未被访问过或访问频率低的页,本质上是不是很像呢?所以大家都是用了相同的bit,做了类似的事情。回到正题,David Rientjes在2007年提了一个patchhttp://lkml.iu.edu/hypermail/linux/kernel/0702.1/0628.html,用于从内核导出文件/proc/PID/clear_refs,用户可以在用户态通过对特定进程清理page referenced flag,这样在/proc/PID/smaps文件中就可以查看被访问过的内存大小了。
这个工具的缺陷非常明显,比如可能影响到被测试的业务进程(比如延迟增加10%,对于100G内存的进程,影响时间超过1s),而且该工具自身也需要消耗system time。另外,该工具由于从用户态接口清理了page referenced flag,这也将影响到LRU算法的准确度,尤其是swap打开以后,很可能将一些热内存页判定为冷内存并swap到disk。更严重的是,一些老内核还有panic风险。在Linux 4.3+版本中的引入了idle page flag特性可以解决此处提到的部分缺陷,后文再详细介绍。
WSS profile charts
brendangregg大神尤其擅长将各种性能数字图形化,本文当然也不例外。wss.pl支持profile模式(-P),以等比数列步长(即当前步长 = 上一次步长 * 2)进行统计,输出如下:
每相邻两行的采集间隔成等比递增:短采样间隔可以用来评估进程对cpu cache的利用,长采样间隔则用来评估进程的物理内存使用趋势。注意这仅是采集一轮的数据(译者注:仅在采样的初始阶段清理一次page referenced flag,可以理解为 1* write + N * read,如果读者想得到更一般化的数据,则应该采集多轮)。将上面的采集数据图形化展示:
uniform 是指100M地址空间内uniform access distribution (译者注:应是指“匀速”访问100M地址空间),可以看到除第一个点外,其他点均稳定在100M,这是因为此时uniform访问的进程还没来得及访问整个地址空间。为了对比,将地址空间调整为2G,如下图所示(分别是对数坐标曲线以及线性曲线):
Method 2: Idle Page Flag
Idle page flag 是Vladimir Davydov在Linux4.3中实现的一个新特性,引入了两种新的page flag:idle和young,它弥补了方案一的一个重要缺陷:影响page reclaim的逻辑。该方案仍然是基于PTE的accessed bit,通过在page_ext_flags引入了额外的idle&&young page flag来保证page reclaim的逻辑不受此影响(译者注:此处关于idle page tracking实现的描述不够准确,译者理解如下:方案一的缺陷在于清理PTE的accessed bit会导致page reclaim的逻辑误判某些热页为冷页,那么通过引入一个软件上的young flag来辅助记录此页为热页,清理accessed bit时将flag置位。这样page reclaim如果遇到young flag置位的页则认为其最近同样被访问过)。另外,上述两个flag在64bit的kernel中被直接定义为page flag,在32bit的kerne中由于page flags空间不够用,则基于page extension特性来定义。以下摘自内核源码树中的文档Documentation/vm/idle_page_tracking.txt vm/idle_page_tracking.txt:
That said, in order to estimate the amount of pages that are not used by a workload one should:
Mark all the workload’s pages as idle by setting corresponding bits in /sys/kernel/mm/page_idle/bitmap. The pages can be found by reading /proc/pid/pagemap if the workload is represented by a process, or by filtering out alien pages using /proc/kpagecgroup in case the workload is placed in a memory cgroup.
Wait until the workload accesses its working set.
Read /sys/kernel/mm/page_idle/bitmap and count the number of bits set. If one wants to ignore certain types of pages, e.g. mlocked pages since they are not reclaimable, he or she can filter them out using /proc/kpageflags.
brendangregg基于此特性写了两个版本的工具,在github https://github.com/brendangregg/wss 可以获取源码,运行截图如下:
这里v1与v2在统计结果上没有差别,主要在于实现方式上:v1每次是一个page为单位进行处理,而v2是batch处理,以maps文件中的每一行(即vma)为单位进行处理,时间消耗从44s降为0.8s。(译者注:之前提到的译者自己写的工具也实现了类似的功能,采用的是v1与v2的折中方案,每次以65536个page为单位处理,不过考虑到测量进程本身的CPU开销以及内存使用,最后放弃该方案)。brendangregg还提到了如果pagemap,idlebitmap,kpagecgroup等支持mmap(2)系统调用,可以避免过多的系统调用。同时大神还想一次性把系统所有page的idle flag都设置上,这样可以得到整机的快照(译者注:idle page tracking只支持扫描LRU链表上的页,对net/kmalloc等kmem是透明的)。另外,第一次采样间隔预期是0.01s(而目前扫描一次最小消耗0.8s),为了实现这个目标,brendangregg提到可以通过发送SIGSTOP以及SIGCONT让被测量的进程停止运行,显然这很可能影响进程的正常逻辑,比如影响tcp窗口,触发超时等。(译者注:brendangregg似乎更关注于细粒度的采样,辅助性能分析;其实粗粒度采样也有参考价值,可以分析内存利用率或者集群调度等,此为后话)。
结语
由于目前没有有效的工具来测量WSS,所以brendangregg大神尝试写了两个小工具。同时他还有一篇文章提到了一些其他方案来预估WSS,比如PMC,见
http://www.brendangregg.com/wss.html
里面有一些更深入的讨论,读者有兴趣可自行前往一观。另外,译者在阿里内部也实现了几个不同版本的工具,实现原理类似,方法则有不小的差异,欢迎大家来阿里一起切磋。
【转帖】系统软件工程师必备技能-进程内存的working set size(WSS)测量的更多相关文章
- 高级Linux运维工程师必备技能(扫盲篇)
高级Linux运维工程师必备技能(扫盲篇) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在了解文件系统之前,我们要学习一下磁盘存储数据的方式,大家都知道文件从内存若要持久化存储的 ...
- 详解Linux运维工程师必备技能
张戈大神是腾讯的一名运维,张戈博客也是我接触到第一个 Linux 运维师的博客,最近也在接触 Linux,说到工具,在行外可以说是技能,在行内一般称为工具,就是运维必须要掌握的工具. 我就大概列出这几 ...
- 浅谈Linux系统运维工程师必备技能
一.什么是运维工程师 相信读者们必定听说过Linux,也听说过运维工程师.那么运维工程师是个什么概念呢? 百度百科上的官方解释如下: 运维工程师(Operations)在国内又称为运维开发工程师(De ...
- Java初级进阶中高级工程师必备技能
很多人学了javase以为自己学的已经很OK了,但是其实javase里边有很多的知识点是你不知道的,不管你找的是哪里的javase的视频,大多数是不会讲这些东西,而这些东西你平时业务又不会主动去接触, ...
- iOS开发工程师必备技能(持续更新)
Objective-C Objective-C语言基础 library,framework的制作 Runtime 编程 LLVM 原理和调优 操作系统 iOS内存管理和调优 iOS的文件系统和沙盒机制 ...
- 详解linux运维工程师入门级必备技能
详解linux运维工程师入门级必备技能 | 浏览:659 | 更新:2013-12-24 23:23 | 标签:linux it自动化运维就是要很方便的运用各种工具进行管理维护,有效的实施服务器保护 ...
- 百度Hr分享,一个合格的数据工程师简历中必备技能?
如果你是一名数据科学方面的求职者,你肯定想知道在简历上写些什么才能获得面试的机会:如果你想进入这个领域,你一定想知道具备哪些技术才能成为一名有竞争力的求职者. 在本文中,我们对Indeed中一千份数据 ...
- 【PS切图】前端工程师必备,但又无需精通的一项技能。
前端主要从事一些代码开发工作,PS使用是前端工程师必备,但又无需精通的一项技能. 前端切图四大面板:在“窗口”菜单下开启 1,信息(手动开启)2,字符(手动开启)3,历史记录(手动开启)4,图层(默认 ...
- Android高工必备技能
转载:http://www.jianshu.com/p/d791bbede02c Step 1. 玩转RxJava 使用RxJava处理异步极其方便,各种操作符可以对数据做流水线式操作,再加上与Ret ...
随机推荐
- IT公司PM沟通那儿些事(一)
本质:传递信息 沟通是不同的行为主体,通过各种载体实现信息的双向流动,形成行为主体的感知,以达到特定目标的行为过程. 信息的准确性弥足珍贵,在工作中,沟通传递的是应该是信息本身,而非情绪. 目标:解决 ...
- 【学习笔记】tensorflow基础
目录 认识Tensorflow Tensorflow特点 下载以及安装 Tensorflow初体验 Tensorflow进阶 图 op 会话 Feed操作 张量 变量 可视化学习Tensorboard ...
- MySQL高级特性——绑定变量
从MySQL 4.1 版本开始,就支持服务器端的绑定变量,这大大提高了客户端和服务器端数据传输的效率 介绍 当创建一个绑定变量 SQL 时,客户端会向服务器发送一个SQL语句的原型.服务器端收到这个S ...
- Go开发之路(目录)
知识点 1. Go语言 简介 2. Go语言 基本语法 3. Go语言 strings以及strconv的使用 4. Go语言 时间和日期类型 5. Go语言 指针类型 6. Go语言 流程控制 7. ...
- C++玄学预编译优化
#pragma GCC diagnostic error "-std=c++11" #pragma GCC optimize("-fdelete-null-pointer ...
- python 图片在线转字符画预览
文章链接:https://mp.weixin.qq.com/s/yiFOmljhyalE8ssAgwo6Jw 关于python图片转字符画,相信大家都不陌生,经常出现在 n个超有趣的python项目中 ...
- 2019Java查漏补缺(一)
看到一个总结的知识: 感觉很全面的知识梳理,自己在github上总结了计算机网络笔记就很累了,猜想思维导图的方式一定花费了作者很大的精力,特共享出来.原文:java基础思维导图 自己学习的查漏补缺如下 ...
- 转摘app测试方法总结
app测试方法总结 一.安全测试 1.软件权限 1)扣费风险:包括短信.拨打电话.连接网络等. 2)隐私泄露风险:包括访问手机信息.访问联系人信息等. 3)对App的输入有效性校验.认证.授权.数 ...
- 使用django 中间件在所有请求前执行功能
django中间是一个轻级,低耦合的插件,用来改变全局的输入和输出. 一 如何使用中间件 定义中间件 注册中间件 # 这是一个中间件代码片段的说明,在各个位置的代码将在何时执行 def simple_ ...
- SQLServer之修改视图
修改视图注意事项 修改先前创建的视图. 其中包括索引视图. ALTER VIEW不影响相关的存储过程或触发器,并且不会更改权限. 如果原来的视图定义是使用 WITH ENCRYPTION 或 CHEC ...