2008年12月29日星期一

Linux下如何监控程序具体使用内存情况

作者: Sam(甄峰) sam_code@hotmail.com

公司在Canmore下作游戏时,因为Canmore可用Memory不大,所以必须常常查看游戏具体使用多少内存。

Sam发现有以下几种方式可以查看当前程序内存使用量:

1. #ps
然后查看VSZ 项目。但这一项只是任务虚拟地址空间大小。并不代表真的使用如此多内存。
ps并没得出进程真实用了多少内存。它计算的是假设系统上只存在这唯一运行的进程时,此进程所占用的内存。事实是,几乎每时每刻系统上有一大堆进程在运行,也就是说ps报告的数据毫无疑问是“错”的。
Linux上大多数程序使用了共享库。例如KEdit使用了好几个KDE的,好几个Xlib的,还有好几个系统库。这些库,其中最常用的恐怕是libc库,同时被Linux系统中要多程序使用着。经过这种共享,Linux可以耍这么一个花招:可以把共享库拷入内存中然后到处引用给每一个程序。
很多工具程序没有考虑这一点。它们只是简单计算一下,而不考虑共享库起的作用。两个程序的共享库部分因此可能被统计了两次内存占用,这样多计算了一次可能导致很多误会。
实际上真实的内存占用是很难获得的。你不仅仅要知道系统如何工作,而且你必须在一些很难判断的问题上作出决定。如,被进程唯一使用的共享库是否应该被统计在内?被多个进程使用的共享库是否应该被统计多次,或者忽略不计?这里并没有一个严格的规则。在不同的情况下,你应该需要不同的选择。可想而知为什么ps在解决这个问题的时候,给出的答案比较含糊。


2. #top -d 1
然后查看VSZ 项目,也只是任务虚拟地址空间大小。并不代表真的使用如此多内存。
所以Sam常常使用如下方法:
在运行前后将比较used以及free和cached的用量。则可推断出实际使用量。
Mem: 33400K used, 160300K free, 0K shrd, 0K buff, 14056K cached
VSZ也会遇到与#ps出来的VSZ同样的问题。

注意:#top 时,会有一个cached值用来表示交换区域,这个区域大小总变化,很不利于我们通过两次的差值看大小。可以这样处理。
#echo 3 > /proc/sys/vm/drop_caches
#sync
然后 cached的值就会被固定。注意,echo 后面的值可以为:1,2,3


3. #free
然后查看2次运行的差值,这表明此程序内存使用量。



4. cat /proc/uid/statm
999 184 146 7 0 577 0
分别表示:
Size (total pages) 任务虚拟地址空间的大小 VmSize/4
Resident(pages) 应用程序正在使用的物理内存的大小 VmRSS/4
Shared(pages) 共享页数 0
Trs(pages) 程序所拥有的可执行虚拟内存的大小 VmExe/4




具体到一个程序中:内存使用量如何呢:
Sam试验表明:
如果某个程序什么都不作。
只是while(1)
则使用cat /proc/uid/statm。发现也会使用256K程序。这可能是分配给它的栈以及glibc库所占位置。

如果Sam这个程序代码什么都不作,但编译时添加 -lBTX, -lbluetooth, -lpthread.
则 #cat /proc/uid/statm发现多用100K物理内存。这表明Linux在计算内存使用量时,会把动态库所占内存包含进去。

没有评论: