前言
前几天有同窗问了一个问题:html
我
ps aux
看到的RSS内存只有不到30M,可是free看到内存却已经使用了7,8G了,已经开始swap了,请问ps aux的实际物理内存统计是否是漏了哪些内存没算?我有什么办法肯定free中used的内存都去哪儿了呢?linux
这个问题不止一个同窗遇到过了,以前子嘉同窗也遇到这个问题,内存的计算老是一个迷糊帐。咱们今天来把它算个清楚下!web
解答
一般咱们是这样看内存的剩余状况的:面试
$free -m
total used free shared buffers cached
Mem: 48262 7913 40349 0 14 267
-/+ buffers/cache: 7631 40631
Swap: 2047 336 1711
那么这个信息是如何解读的呢,如下这个图解释的挺清楚的!bash
上面的状况下咱们总的内存有48262M,用掉了7913M
。其中 buffer+cache
总共 14+267=281M
, 因为这种类型的内存是能够回收的,虽然咱们用掉了 7913M
,可是实际上咱们若是实在须要的话,这部分buffer/cache
内存是能够放出来的。微信
咱们来演示下:运维
$ sudo sysctl vm.drop_caches=3
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
咱们把 buffer/cache
大部分都清除干净了,只用了44M,因此咱们此次 used
的空间是7676M。编辑器
到如今咱们比较清楚几个概念:ide
-
一、总的内存多少 -
二、buffer/cache内存能够释放的。 -
三、used的内存的几率。
即便是这样咱们仍是要继续追查下used的空间(7637M)到底用到哪里去了?工具
这里首先咱们来介绍下 nmon
这个工具,它对内存的使用显示比较直观。
使用的内存的去向咱们很天然的就想到操做系统系统上的各类进程须要消耗各类内存,咱们透过top工具来看下:
一般咱们会看进程的RES
这一项,这项究竟是什么意思呢?这个数字从哪里出来的呢?经过strace
对top
和nmon
的追踪和结合源码,咱们肯定这个值是从/proc/PID/statm
的第二个字段读取出来的.
那这个字段什么意思呢?
man proc 或者 http://www.kernel.org/doc/man-pages/online/pages/man5/proc.5.html 会详细的解释/proc/下的文件的具体意思,咱们摘抄下:
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
从数字来看,咱们的进程使用了大概7024M内存,距离7637M还有几百M内存哪里去了?哪里去了?猫吃掉了?
咱们再回头来仔细看下 nmon
的内存统计表。
那个该死的slab是什么呢?那个PageTables又是什么呢?
简单的说内核为了高性能每一个须要重复使用的对象都会有个池,这个slab池会cache大量经常使用的对象,因此会消耗大量的内存。运行命令:
$ slabtop
咱们能够看到:

从图咱们能够看出各类对象的大小和数目,遗憾的是没有告诉咱们slab
消耗了多少内存。咱们本身来算下好了:
$ echo `cat /proc/slabinfo |awk 'BEGIN{sum=0;}{sum=sum+$3*$4;}END{print sum/1024/1024}'` MB
904.256 MB
好吧,把每一个对象的数目*大小,再累加,咱们就获得了总的内存消耗量: 904M
那么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%
好吧,知道是干吗的啦,管理这些物理页面的硬开销,那么具体是多少呢?
$ echo `grep PageTables /proc/meminfo | awk '{print $2}'` KB
58052 KB
好吧,小结下!内存的去向主要有3个:
-
一、进程消耗。 -
二、slab消耗 -
三、pagetable消耗。
我把三种消耗汇总下和free出的结果比对下,下面把命令汇合在一块儿:
$ cat cm.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`
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 报告说 7629M
, 咱们的cm脚本报告说 7800.3M
, 咱们的CM多报了 171M
。
damn,这又怎么回事呢?
咱们从新校对下咱们的计算。咱们和nmon来比对下,slab和pagetable的值是吻合的。那最大的问题可能在进程的消耗计算上。
resident resident set size 包括咱们使用的各类库和so等共享的模块,在前面的计算中咱们重复计算了。
$ pmap `pgrep bash`
...
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
多出的171M正是共享库重复计算的部分。
可是因为每一个进程共享的东西都不同,咱们也无法知道每一个进程是如何共享的,无法作到准确的区分。
因此只能留点小遗憾,欢迎你们来探讨。
总结:
内存方面的概念不少,须要深刻挖掘!
祝玩的开心!
做者:Yu Feng 原文:http://blog.yufeng.info/archives/2456
热门文章推荐
-
Kubernetes v1.19.0 正式发布! -
Kubectl 备忘录 -
Harbor v2.0 镜像回收那些事 -
IT运维面试问题总结-基础服务、磁盘管理、虚拟平台和系统管理 -
聊聊 resolv.conf 中 search 和 ndots 配置 -
磁盘空间分析神器 - ncdu
最后
-
欢迎您加我微信【 ypxiaozhan01】,拉您进技术群,一块儿交流学习... -
欢迎您关注【 YP小站】,学习互联网最流行的技术,作个专业的技术人...

本文分享自微信公众号 - YP小站(ypxiaozhan)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。