对于Linux系统程序开发人员,经常需要和进程所使用的内存情况打交道,比如,分析程序的内存泄漏问题。这时候我们可能使用ps、top、procrank、dumpsys(后两个命令为Android系统)来跟踪、调试进程内存的使用情况。上述几个工具进程涉及到的几个比较的重要的概念:VSS、RSS、PSS、USS,对于这几个概念,大家总是存在一种似曾相识,却又不甚了解的感觉,这对于真正的把握进程内存使用情况是十分有害的。所以,本文旨在彻底分析这个四个概念,弄清各个量之间的联系和区别,提供有助于解释各种工具的内存报告的信息,以便确定Linux进程和系统的实际内存使用量,为以后分析内存问题提供坚实的理论基础。
基本概念
- VSS:Virtual Set Size 虚拟耗用的内存(包含与其他进程共享占用的虚拟内存)
- RSS:Resident Set Size 实际使用的物理内存(包含与其他进程共享占用的内存)
- PSS:Proportional Set Size 实际使用的物理内存(按比例包含与其他进程共享占用的内存)
- USS:Unique Set Size 进程独自占用的物理内存(不包含与其他进程共享占用的内存)
对于单个进程,一般来说内存占用大小排序如下:VSS >= RSS >= PSS >= USS
概念解析
Android有一个名为procrank(/system/xbin/procrank)的工具,它列出了Linux进程的内存使用量,并按使用量的高低排序。每个进程报告的内存使用情况分为VSS、RSS、PSS和USS。
为了简单起见,在这个描述中,内存将用页面而不是字节来表示。像我们这样的Linux系统在最低级别上以4096字节的页面管理内存。
下面分别具体解释一下各个概念的含义:
- VSS(ps工具中表示为VSZ)表示进程总的可访问地址空间。这个大小还包括可能不驻留在RAM中的内存,比如使用malloc分配内存后,尚未写入数据的内存。VSS对于确定进程的实际内存使用量几乎没有什么用处。
- RSS表示一个进程在RAM中实际拥有的总内存。RSS可能具有误导性,因为它包括了该进程与其他进程共享的实际物理内存使用量,例如,对于共享库,其往往只加载到内存中一次,而不管有多少进程使用它。RSS不能准确地表示单个进程的内存使用情况。
- PSS与RSS不同之处是,对于进程间共享的内存,其按比例报告其所使用的共享物理内存大小。比如有n进程同时在使用一个共享库,那对于单个进程其占用的该共享库的内存为1/n。如果三个进程都使用一个有30页的共享库,那么这个库将只向每个进程报告的PSS贡献10页。PSS是一个非常有用的数字,因为当系统中所有进程的PSS加在一起时,就可以很好地表示系统中总的内存使用量。当一个进程被终止时,贡献给它的PSS的共享库将按比例分配给仍然使用该库的其他进程的PSS总数。这样,PSS可能有点误导人,因为当进程被终止时,PSS不能准确地表示返回到整个系统的内存。
- USS表示进程占用的总的物理内存大小,也就是说这部分内存是该进程完全独占的。 USS是一个非常有用的数字,因为它表示运行特定进程的实际增量成本。当进程被终止时,USS是实际返回给系统的总内存。当最初怀疑某个进程存在内存泄漏时,USS是最好的监视数字。
对于使用Python的系统,还有一个很好的工具叫做ledsmem,它可以报告内存统计信息,包括所有这些类别。
NOTE:这里有几个问题需要注意:
- 两个进程共享的部分,远远不是只有共享库,比如我们在Linux里面开2个bash进程,那么这2个bash,实际是共享1个代码段;其他的mmap()的时候shared的映射当然也是两个进程共享的内存。
- 共享库里面的内存,也不是都共享,只是代码段等不会做CoW(写时拷贝)的内存才会跨进程共享。
- USS去掉的是所有跨进程共享的内存,不是只去掉了共享库。
实例解析
下面通过一个实例,具体解析各个量之间的关系。假设Linux下有两个bash进程、一个cat进程,进程ID分别为1044、1045、1054,下面通过公式分别计算VSS、RSS、PSS、USS:
- VSS = 1 + 2 + 3
- RSS = 4 + 5 + 6
- PSS = 4/3 + 5/2 +
- USS = 6
上图中的4这片内存,是libc的代码段在内存驻留的部分,被3个进程共享;5这段内存,是bash的代码段,被2个进程(1044和1045)指向。在计算PSS的时候,这些都需要被比例化。
监测工具
对于Linux系统,一般都会提供ps、top两个命令,Android系统还会提供procrank、dumpsys这两个命令。对于ps、top其只能查到VSS、RSS这两个值;procrank、dumpsys可以提供PSS、USS信息,dumpsys meminfo 可以查出native和dalvik分别占用多少内存。另外,dumpsys可以查询到很多有用的系统信息,比如meminfo、cpuinfo、activity、window、wifi、account等信息。