Linux内存消耗

原文:https://web.archive.org/web/20120520221529/http://emilics.com/blog/article/mconsumption.html

本文主要描述如何通过一个合理的方法来测量linux进程的内存消耗。linux包含了虚拟内存管理的特性,因此,内存消耗并没有想想中的那么简单。

心急速览

对于心急的人,我先给出结论。我倾向于使用PSS(Proportional Set Size)来测量内存消耗,前提是你的Linux系统支持。下面的Python方法,可以以KiB为单位返回指定进程ID的PSS。

import sys, re

def pss_of_process(pid):
    with file('/proc/%s/smaps' % pid) as fp:
        return sum([int(x) for x in re.findall('^Pss:\s+(\d+)', fp.read(), re.M)])

完整脚本:
https://web.archive.org/web/20130227090134/http://emilics.com/media/pub/pss.py
执行脚本,运行后获取所有用户运行进程PSS内存消耗(NEW BSD协议)

% sudo python pss.py
USER             PID    PSS  COMMAND
postgres        1308  29521  postgres: writer process
root            1867  21983  /usr/bin/X :0 vt7 -nolisten tcp -auth /var/...
www-data       28752  14507  /usr/sbin/apache2 -k start
www-data       28753  13669  /usr/sbin/apache2 -k start
...

我们介绍三种概念来观测Linux进程的内存消耗。VSZ、RSS和PSS。

尽管有点不准确,但是我们考虑这样一个场景。假设有三个人共同租住1个房子。每个人代表一个进程,生活费代表内存消耗。在这个场景中,测量一个进程的内存消耗相当于计算1个人的生活费。

每个人都独自占有他们自己的电话线。VSZ、RSS、PSS这三个指标都会单独计算每个人的电话费用,这是没有任何问题的。

这个房子有一个车库,付费的人可以使用,但是他们都不开车,所以他们都不会使用这个车库。但是VSZ会在每个人的生活费上计算车库的费用,尽管车库只是留置给他们使用的。因此,VSZ代表了所有东西的总的生活费用,不管他们实际使不使用。RSS和PSS只计算他们实际上使用的费用,因此,他们不会计算车库的费用,因为没有使用。

因为他们一起使用网络和电视,他们均摊这些费用。但是RSS会将全部的费用计算在每个人的头上,即使他们是一起使用,而且还均摊费用。RSS就是假设网络和电视的费用是没有跟任何人分享的。

PSS只会每人计算1/3的网络和电视费用,因为他们均摊了。这个比RSS更合理一些。

我们使场景更复杂些,方便我们理解PSS的局限性。他们中一个人经常上网,但几乎不怎么看电视。因此理论上这个人应该付50%的网络费用和20%的电视费用。但是PSS无法表述这种情况。它只能简单的计算每个人1/3的网络费用和电话费用。

我认为使用PSS更加合理。但是有局限性,有些场景下使用RSS更好。当你想知道如果你搬出去自己生活需要多少生活费时,RSS会更加合理。

虚拟内存管理

通过 ps 命令查看进程信息

#ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
norisky  29065  0.1  0.2   8132  5604 pts/8    Ss   19:03   0:00 zsh
norisky  29075  0.0  0.1  10228  3772 pts/8    S+   19:03   0:00 vi
norisky  29526  8.0  0.5  27708 10676 pts/4    S+   19:05   0:00 emacs -nw
norisky  29527  0.0  0.0   2976  1080 pts/6    R+   19:05   0:00 ps aux

在man手册中,我们可以了解到VSZ和RSS与内存消耗有关。

VSZ virtual memory size of the process in KiB (1024-byte units).  Device mappings are currently excluded; this is
                             subject to change.  (alias vsize).
RSS resident set size, the non-swapped physical memory that a task has used (in kiloBytes).  (alias rssize, rsz)

我们应该使用哪个?

技术术语

  1. Linux内存管理中的一块内存。一般Linux系统上1页是4096字节(4KB)
  2. 物理内存
    指的是实际内存,也就是RAM,计算机主存。
  3. 虚拟内存
    使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),无论实际内存还有多少,其他应用消耗使用了多少。虚拟内存页可以映射到物理内存页。因此,进程只需要考虑使用虚拟内存
VSZ和按需分页

使用VSZ来测量进程内存消耗没有太大的意义。由于存在按需分页这个特性,它会阻止非必要的内存消耗。

例如,emacs文本编辑器有能够处理XML文件的方法。但是这些方法根本没有使用。当用户编辑普通文本时,将这些方法加载到物理内存完全没有必须。按需加载特性使得进程只有在使用时才加载对应的页。

首先,当程序启动时,系统给予进程一个虚拟内存空间,但是并不会将方法功能对应的内存页真的加载到物理内存空间。当程序执行虚拟内存中的方法功能时,CPU中的MMU告诉Linux系统,内存页未加载。而后,Linux暂停进程,加载内存页到主存,将页映射到进程的虚拟内存,然后进程从暂停的位置启动运行。因此,进程并不需要知道它暂停了,只需要假设从虚拟内存加载方法并使用。

VSZ是指进程的整个虚拟内存大小,无论页是否被加载到实际的主存中。因此,它并不是一个真实的指标可以用来测量内存消耗,因为它包含了没有使用的页。

RSS和共享库

RSS描述了进程实际加载到物理内存的页数量。听起来,特别像进程的真实内存消耗,而且比VSZ更精准。但因为共享库或动态链接库的原因,RSS也没有那么简单。

库是一个包含特定功能的模块。例如,libpng.so 处理PNG图片的压缩和解压缩,libxml2.so 处理xml文件。通常不需要每个程序员都编写这些功能,他们可以使用别人写的库来实现他们的目的。

共享库是被多个程序或进程所共享的。例如,当两个同时运行的进程都想要使用 libxml2.so中的XML处理功能时,Linux一旦加载libxml2.so后,将它映射到两个进程的虚拟空间。这两个进程不需要关注他们是否和其他进程共享这些功能,因为他们可以访问这些功能,在他们自己的虚拟空间中使用这些功能。因为这个特性,Linux减少了不必要的重复内存页。

现在,我们回头之前的例子。emacs 拥有可以处理xml文件的功能。这是使用的 libxml2.so共享库。这次,用户确实在处理xml文件,emacs正在使用 libxml2.so。同时,有两个后台进程也在使用 libxml2.so。因为 libxml2.so是共享库,Linux只需要加载libxml2.so 一次到物理内存,然后将该地址映射到这3个进程的虚拟空间就可以了。

如果我们这时查看emacs的RSS,它将包含libxml2.so的内存页。这并没有错,因为emacs确实在使用它。但另外两个进程呢?并不只是emacs在使用这些功能。如果你将这三个进程的RSS相加,libxml2.so尽管只被加载到物理内存1次,却被累加计算了3次。

因此,RSS可以表明当进程独自运行,没有去其他进程共享任何库时,所需要的内存消耗。而在实际中,RSS会过度进程的内存消耗。用来测量一个进程的内存消耗并没有错,但是你需要牢记RSS的行为。

PSS

PSS是一个相对比较新的内存消息测量指标。并不是所有Linux都支持PSS,但如果支持,那它绝对派的上用场。PSS的原理是将共享页平均分配到所有使用它的进程上。

如果存在N个进程在使用共享库,那么每个进程占用1/N共享库内存页。

还是之前的例子,emacs和另外两个进程共享libxml2.so,因为存在3个进程,PSS会假定每个进程占用1/3的libxml2.so的内存页。

我认为PSS相对RSS更加可靠。尤其是考虑系统的整体内存消耗时。例如,当你开发一个多进程的系统时,你想评估你需要为设备配备多大内存时,PSS比RSS更加合适。

ps命令不会打印PSS。你可以使用pss.py的脚本来查看进程的PSS。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值