【转帖】系统软件工程师必备技能-进程内存的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 ...
随机推荐
- 重写(override)和重载(overload)的区别
override(重写): 是进行基类中函数的重写,是面向对象的概念 重载(overload):是方法的名称相同,参数或参数类型不同,进行多次重载以适应不同的需要.overload 是面向对象的概念.
- 永不重复的id生成器
目录 (1)需要导入的包 (2)IdGenerator类 (3)使用举例 (1)需要导入的包 主要用在格式化日FastDateFormat.getInstance("yyyyMMddHHmm ...
- 如何用java控制你的电脑?
用java控制你的电脑 java,是一门强大的语言,强大的地方在于有很多类,我们可以直接的使用.而java.awt.Robot就很有意思了,顾名思义robot机器人,怎样一个机器法,如:控制鼠标方法: ...
- iOS----------viewcontroller中的dealloc方法不调用
ios的viewcontroller生命周期是 init -> loadView -> viewDidLoad -> viewWillAppear -> viewDidAppe ...
- Python第十天 print >> f,和fd.write()的区别 stdout的buffer 标准输入 标准输出 从控制台重定向到文件 标准错误 重定向 输出流和输入流 捕获sys.exit()调用 optparse argparse
Python第十天 print >> f,和fd.write()的区别 stdout的buffer 标准输入 标准输出 从控制台重定向到文件 标准错误 重定向 输出流和 ...
- Expression
表达式目录树 1.什么是表达式目录树Expression? 表达式目录树是一个数据结构,语法树. 首先我们去看看 Expressions类 ,定义了一个泛型委托类型 TDelegate: // 摘要: ...
- Xml文档规则
Xml文档规则: 名字中不能包含空格 名字不能以数字或标点符号开头 左尖括号 < 后不可以有空格 起始和结束标签的大小写必须一致(严格区分大小写) XML文件中出现的第一个元素是根元素 XML文 ...
- Go语言学习笔记-流程控制(二)
Go语言流程控制 字典类型Map 1.上节遗留:map字典类型 变量声明:var myMap map[string] PersonInfo 其中,myMap是变量名,string是键的类型,Perso ...
- telnet操作memcache
1.使用方法 1. 连接到memcached telnet 192.168.1.100 11211 add name 0 60 5 [说明 add 是指令名 name 是key的名字 (是以 ...
- springboot项目屏蔽mq或者mongodb的监控日志输出
最近写项目,用的是springboot,其中用到了rabbitmq和mongodb,配置完成 项目启动后,会输出如下日志: mongodb和mq的检测,会一直打印日志,这样会影响开发人员的测试. 如何 ...