前言
前幾天有同窗問了一個問題: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源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。