认真分析下进程的内存,说说VSZ、RSS、PSS

进程占用的内存可以有以下这些类型:

  1. 自身的代码
  2. 共享库的代码
  3. 运行过程分配的堆和栈
  4. 通过mmap映射的磁盘文件内容

1. 虚拟内存与物理内存

这里要区分两个概念,虚拟内存和物理内存。物理内存对于进程来说是透明的,进程直接操作的是虚拟内存。而数据和代码是存放在真实的物理内存的,之所以进程在虚拟内存中寻址可以获取数据,是因为虚拟内存与物理内存存在着映射关系。

当我们的进程向系统申请内存时,比如通过malloc方法,得到的其实是虚拟内存,如果进程没有使用这些虚拟内存,那么它们是不会和物理内存关联起来的。比如如果我们malloc 10MB的内存,但是只用了一个byte的,那么进程实际得到的只有一个页的物理内存,也就是4096byte的内存空间。当物理内存被换出到磁盘(swap out),虚拟内存对应的地址还是有效的,如果寻址到这些地址,对应的物理内存就会被换入到内存(swap in)。

虚拟内存是连续的,而物理内存却不一定。

2. 共享的内存

从进程自身的角度看,虚拟内存是进程独立的,所有内存都是私有的,包括自身代码、共享库、堆栈等,它不用关心共享内存的事情。但实际上在物理内存的层面,很多东西是可以共享的,比如共享的代码库(.so)、自身代码甚至是自身运行时私有的堆栈内存。

2.1 共享库

同一个共享库的代码在物理内存中只会存在一份,这块内存会映射到不同进程的虚拟内存中,对各个进程来说,就像是自己私有的内存一样,而对于系统来说,则是节省了内存的资源。

2.2 进程自身的代码

同样,同一份代码运行起来的多个进程是共享这些代码的内存的,因为可执行代码类型的内存页是只读的(除非是debugger模式),没有必要复制多份,因此在实际场景中,当我们启动一个大应用程序后,再启动它的另一个实例,第二次启动会快很多,这就是因为其代码已经在内存中了,无需再重新加载一遍。

2.3 进程自身的私有内存

如果从一个进程fork出一个子进程,那么父进程的私有内存(比如堆栈)则会与子进程共享,但会被标记成(copy-on-write),意思是如果两个进程都没有修改这些内存页,那么这些内存页在两个进程间就是共享的,但如果某个进程要修改某个页了,那么这个页就会先被复制一份,再被修改。

3. 进程内存的数据统计

在OSX系统,可以运行以下命令来查看某个进程内每一块内存的类型(mapped file、Stack内存、malloc内存、代码的__DATA或者__TEXT段等),以及大小、是否共享或者copy-on-write等。

sudo vmmap <pid>

如果只是关注RAM的内存,可以加上-resident参数:

sudo vmmap -resident <pid>

比如指定Firefox进程,有如下输出:

可以看到,Firefox进程的代码和库代码加载了108MB__TEXT段数据,字体支持(ATS)需要33MB内存,但只有2.5MB真正加载在物理内存中,它通过MALLOC申请了256MB内存,并且247MB在物理内存中,它有14MB用于栈内存,但只用了248KB。

4. 进程内存大小的度量方法

提到进程消耗的内存大小,我们或多或少听到VSZ、RSS、PSS,那么它们代表的是什么呢?有了上述的知识背景,现在来分析或许能更加清晰。

4.1 VSZ(Virtual Memory Size)

指的是虚拟内存的大小,进程运行理论需要的内存大小,用这个来表示进程消耗了多少内存其实没有太大的意义,因为它包含了未被加载到实际内存中的空间。举个例子,假如有个文本编辑器叫做emacs,它有个编辑xml文件的功能,但这个功能比较少被用到,因为用户一般情况下是编辑普通的文本,因此没有必要一启动就把这个功能的代码加载到内存中。

除非用户真实用到某个页,否则系统不会把这个页加载到内存,这其实称为demand paging feature。

来看一下上面这个例子中虚拟内存工作的流程。首先启动应用程序,系统为进程分配了运行编辑xml所需要的虚拟内存,但并没有真正把这些功能所在的页加载到物理内存。当进程真正调用到编辑xml的功能,CPU上的MMU模块将会告诉系统,对应的虚拟内存页发生缺页了,那么系统就会暂停运行中的进程,把对应的页加载到内存,再把这些物理内存页映射到虚拟内存上,最后让应用程序从暂停的地方继续执行。对于进程来说,它是不知道自己被暂停了的,它只需要简单地认为对应的功能已经加载在虚拟内存上了,并使用它就好了。

虚拟内存描述了进程运行时所需要的总内存大小,包括了那些还没有被加载到实际内存中的代码和数据。

4.2 RSS(Resident Set Size)

RSS表示了进程中真正被加载到物理内存中的页的大小。但是用它来表示进程占用的内存大小也不太合适,因为还有个共享代码库的概念(Shared Libraries)。

比如libxml2.so这个程序库,有多个进程会用到它,而系统在物理内存只会加载一遍这个代码库,然后这块物理内存会被映射到不同进程的虚拟内存空间中,对于单独的进程来说,就像是这个库只加载在自己的虚拟内存中一样,不需要关心它是否与其它进程共享。

而进程的RSS是包含这块共享库的内存空间的,因此如果简单把系统中所有进程的RSS相加的话,结果是比系统总的内存大的,因为共享库占的内存被计算了多遍。

4.3 PSS(Proportional Set Size)

PSS在VSS的基础上,将共享库的内存按使用的进程个数平均分成多份。假如有N个进程使用libxml2.so这个库,这个库加载了200K代码在内存中,那么每个进程的PSS值中有(200 / N)K 的大小是这个共享库贡献的。

如果把系统中所有进程的PSS值加起来,就等于系统所有进程占用的内存总大小。

但是PSS并不是在所有的Linux系统中都有提供的,比如ps命令中就没有PSS值,而Android的adb shell dumpsys meminfo <pid>命令就可以看到进程的PSS值。

4.4 总结一下三种度量方法

如果要度量进程占用的内存大小,较好的选择是使用PSS,用RSS也行,不过要注意有些内存是和别的进程共享的。

再举个例子总结一下前面三个概念,比如一个进程有500K的代码并且链接了2500K的共享库,然后有200K的堆栈分配。其中有400K自身的代码、1000K的共享库以100K的堆栈内存被加载在实际内存(RAM)中,并且系统中一共有两个进程用了同样的共享库。那么:

VSZ:500K + 2500K + 200K = 3200K
RSS:400K + 1000K + 100K = 1500K
PSS:400K + (1000K / 2) + 100K = 1000K

5. 命令执行结果

在Android的adb shell中执行ps命令的结果:

  1. 执行adb shell ps
  1. 执行adb shell dumpsys meminfo com.android.calendar

6. 参考文献:

  1. https://stackoverflow.com/questions/7880784/what-is-rss-and-vsz-in-linux-memory-management
  2. https://web.archive.org/web/20120520221529/http://emilics.com/blog/article/mconsumption.html
  3. https://stackoverflow.com/questions/118307/a-way-to-determine-a-processs-real-memory-usage-i-e-private-dirty-rss
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容