前几天小马同学问了一个问题:我ps aux看到的RSS内存只有不到30M,但是free看到内存却已经使用了7,8G了,已经开始swap了,请问ps aux的实际物理内存统计是不是漏了哪些内存没算?我有什么办法确定free中used的内存都去哪儿了呢?这个问题不止一个同学遇到过了,之前小王同学也遇到这个问题,内存的计算总是一个迷糊账。我们今天来把它算个清楚下!通常我们是这样看内存的剩余情况的:$free -m total used free shared buffers cached Mem: 48262 7913 40349 0 14 267 -/+ buffers/cache: 7631 40631 Swap: 2047 336 1711
vm.drop_caches = 3 $ free -m total used free shared buffers cached Mem: 48262 7676 40586 0 3 41 -/+ buffers/cache: 7631 40631 Swap: 2047 336 1711 到现在我们比较清楚几个概念:1. 总的内存多少 2. buffer/cache内存可以释放的。 3. used的内存的概率。即使是这样我们还是要继续追查下used的空间(7637M)到底用到哪里去了? 这里首先我们来介绍下nmon这个工具,它对内存的使用显示比较直观。
那这个字段什么意思呢? man proc或者http://www.kernel.org/doc/man-pages/online/pages/man5/proc.5.html会详细的解释/proc/下的文件的具体意思,我们摘抄下:/proc/[pid]/statm Provides information about memory usage, measured in pages. The columns are: size total program size (same as VmSize in /proc/[pid]/status) resident resident set size (same as VmRSS in /proc/[pid]/status) share shared pages (from shared mappings) text text (code) lib library (unused in Linux 2.6) data data + stack dt dirty pages (unused in Linux 2.6) resident set size 也就是每个进程用了具体的多少页的内存。由于linux系统采用的是虚拟内存,进程的代码,库,堆和栈使用的内存都会消耗内存,但是申请出来的内存,只要没真正touch过,是不算的,因为没有真正为之分配物理页面。我们实际进程使用的物理页面应该用resident set size来算的,遍历所有的进程,就可以知道所有的所有的进程使用的内存。我们来实验下RSS的使用情况:$ cat RSS.sh #/bin/bash for PROC in `ls /proc/|grep "^[0-9]"` do if [ -f /proc/$PROC/statm ]; then TEP=`cat /proc/$PROC/statm | awk '{print ($2)}'` RSS=`expr $RSS + $TEP` fi done RSS=`expr $RSS \* 4` echo $RSS"KB" $ ./RSS.sh 7024692KB 我们再回头来仔细看下nmon的内存统计表。
从图我们可以看出各种对象的大小和数目,遗憾的是没有告诉我们slab消耗了多少内存。我们自己来算下好了:$ echo `cat /proc/slabinfo |awk 'BEGIN{sum=0;}{sum=sum+$3*$4;}END{print sum/1024/1024}'` MB 904.256 MB 那么PageTables呢?我们万能的内核组的同学现身了: 你还没有计算page tables的大小,还有struct page也有一定的大小(每个页一个,64bytes),如果是2.6.32的话,每个页还有一个page_cgroup(32bytes),也就是说内存大小的2.3%(96/4096)会被内核固定使用的 含黛: struct page是系统boot的时候就会根据内存大小算出来分配出去的,18内核是1.56%左右,32内核由于cgroup的原因会在2.3% 58052 KB
#/bin/bash for PROC in `ls /proc/|grep "^[0-9]"` do if [ -f /proc/$PROC/statm ]; then TEP=`cat /proc/$PROC/statm | awk '{print ($2)}'` RSS=`expr $RSS + $TEP` fi done RSS=`expr $RSS \* 4` PageTable=`grep PageTables /proc/meminfo | awk '{print $2}'` SlabInfo=`cat /proc/slabinfo |awk 'BEGIN{sum=0;}{sum=sum+$3*$4;}END{print sum/1024/1024}'` echo $RSS"KB", $PageTable"KB", $SlabInfo"MB" printf "rss+pagetable+slabinfo=%sMB\n" `echo $RSS/1024 + $PageTable/1024 + $SlabInfo|bc` free -m $ ./cm.sh 7003756KB, 59272KB, 904.334MB rss+pagetable+slabinfo=7800.334MB total used free shared buffers cached Mem: 48262 8050 40211 0 17 404 -/+ buffers/cache: 7629 40633 Swap: 2047 336 1711 free报告说7629, 我们的cm脚本报告说7800.3M, 我们的CM多报了171M。 damn,这又怎么回事呢? ... 22923: -bash 0000000000400000 848K r-x-- /bin/bash 00000000006d3000 40K rw--- /bin/bash 00000000006dd000 20K rw--- [ anon ] 00000000008dc000 36K rw--- /bin/bash 00000000013c8000 592K rw--- [ anon ] 000000335c400000 116K r-x-- /lib64/libtinfo.so.5.7 ... 0000003ec5220000 4K rw--- /lib64/ld-2.12.so 0000003ec5221000 4K rw--- [ anon ] 0000003ec5800000 1628K r-x-- /lib64/libc-2.12.so ... 0000003ec5b9c000 20K rw--- [ anon ] 00007f331b910000 96836K r---- /usr/lib/locale/locale-archive 00007f33217a1000 48K r-x-- /lib64/libnss_files-2.12.so ... 00007f33219af000 12K rw--- [ anon ] 00007f33219bf000 8K rw--- [ anon ] 00007f33219c1000 28K r--s- /usr/lib64/gconv/gconv-modules.cache 00007f33219c8000 4K rw--- [ anon ] 00007fff5e553000 84K rw--- [ stack ] 00007fff5e5e4000 4K r-x-- [ anon ] ffffffffff600000 4K r-x-- [ anon ] total 108720K 但是由于每个进程共享的东西都不一样,我们也没法知道每个进程是如何共享的,没法做到准确的区分。所以只能留点小遗憾,欢迎大家来探讨。总结:内存方面的概念很多,需要深入挖掘!祝玩的开心! |
微信公众号
手机版