Linux--Dentry內存持續增長問題分析


查看內存使用情況

## 執行命令
cat /proc/meminfo

## 輸出結果
## 服務器總內存
MemTotal:       132030344 kB
## 服務器空閑內存
MemFree:         1396884 kB
## Buffer使用的內存
Buffers:          409812 kB
## Cache使用的內存
Cached:         53136072 kB
## 使用Slab分配的內存。
Slab:           16681824 kB
## 使用Slab分配且可回收內存。
SReclaimable:   16592540 kB
## 使用Slab分配但不可以回收內存。
SUnreclaim:        89284 kB

查看slab方式分配的內存

可以使用/proc/slabinfo文件來查看Slab分配的內存情況,如:

## 執行命令
cat /proc/slabinfo  |head -n 10

## 輸出結果
slabinfo - version: 2.1
# name            <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> : tunables <limit> <batchcount> <sharedfactor> : slabdata <active_slabs> <num_slabs> <sharedavail>
fib6_nodes            19     59     64   59    1 : tunables  120   60    8 : slabdata      1      1      0
ip6_dst_cache         13     20    384   10    1 : tunables   54   27    8 : slabdata      2      2      0
ndisc_cache            0      0    256   15    1 : tunables  120   60    8 : slabdata      0      0      0
ip6_mrt_cache          0      0    128   30    1 : tunables  120   60    8 : slabdata      0      0      0
RAWv6                 27     28   1088    7    2 : tunables   24   12    8 : slabdata      4      4      0
UDPLITEv6              0      0   1024    4    1 : tunables   54   27    8 : slabdata      0      0      0
UDPv6                  2      8   1024    4    1 : tunables   54   27    8 : slabdata      2      2      0
tw_sock_TCPv6          0      0    320   12    1 : tunables   54   27    8 : slabdata      0      0      0

但上述結果需要自行計算各模塊使用的內存情況,可以使用slabtop來查看主要的內存使用:

## 執行命令
slabtop --sort=c -o |head -n 17

## 輸出結果
 Active / Total Objects (% used)    : 87179810 / 89818826 (97.1%)
 Active / Total Slabs (% used)      : 4166722 / 4166821 (100.0%)
 Active / Total Caches (% used)     : 105 / 184 (57.1%)
 Active / Total Size (% used)       : 15364477.91K / 15662436.88K (98.1%)
 Minimum / Average / Maximum Object : 0.02K / 0.17K / 4096.00K

  OBJS 		ACTIVE  	USE 	  OBJ SIZE  	SLABS 		OBJ/SLAB 	CACHE SIZE 		NAME
73443720 	73407245  	99%    		0.19K 		3672186       	20  	14688744K 		dentry
15713530 	13234322  	84%    		0.10K 		424690       	37   	1698760K 		buffer_head
303044 		244340  	80%    		0.55K  		43292        	7    	173168K 		radix_tree_node
 41660  	41411  		99%    		0.98K  		10415        	4     	41660K 			ext4_inode_cache
  1053   	1053 		100%   		16.00K   	1053        	1     	16848K 			size-16384
   183    	183 		100%   		32.12K    	183        		1     	11712K 			kmem_cache
  1129   	1079  		95%    		8.00K   	1129        	1      	9032K 			size-8192
118177  	74869  		63%    		0.06K   	2003       		59      8012K 			size-64
 28260  	28104  		99%    		0.19K   	1413       		20      5652K 			size-192
  7452   	7259  		97%    		0.64K   	1242        	6      	4968K 			proc_inode_cache

命令slabtop介紹

slabtop displays detailed  kernel  slab  cache  information in real time. It displays a listing of the top caches sorted by one of the listed sort criteria.  It also displays a statistics header filled with slab layer information.
slabtop命令可實時顯示內核slab緩存信息,linux系統透過/proc/slabinfo來向用戶暴露slab的使用情況。
PS:請勿在進程較多或內存較大的服務器如Redis服務器上運行slabtop命令。

查看dentry狀態

dentry的使用狀態可以使用/proc/sys/fs/dentry-state來獲取:

## 執行命令
cat /proc/sys/fs/dentry-state
## 輸出信息
nr_dentry	nr_unused	age_limit	want_pages	nr_negative	  dummy		
73563262    73554846       45    	 	  0      	 0         	0

查看dentry增長情況

通過腳本來監控slab可以回收內存dentry使用內存的增長情況:

while true; 
do
    date_str=`date "+%Y-%m-%d %H:%M:%S"`;
    memory_info=`cat /proc/meminfo |grep SReclaimable`;
    dentry_info=`cat /proc/slabinfo  |grep dentry`;
    echo "${date_str}    ${memory_info}";
    echo "${date_str}    ${dentry_info}";
    sleep 1; 
done

觀察dentry內存回收

通過監控可發現dentry內存持續增長,可以通過監控dentry內存分配(d_alloc)和內存釋放(d_free)來定位,創建dentry_chek.stp文件:

## dentry.stp
## 監控kernel上dentry內存分配和內存釋放的進程信息
probe kernel.function("d_alloc")  
{
    printf("%s[%ld] %s %s\n", execname(), pid(), pp(), probefunc())
}
probe kernel.function("d_free")  
{
    printf("%s[%ld] %s %s\n", execname(), pid(), pp(), probefunc())
}
probe timer.s(5)  
{
    exit()
}                                                               

執行腳本並分析結果:

## 執行腳本並輸入到日志文件
stap dentry_chek.stp 1>/tmp/dentry_chek.log 2>&1

## 分析日志文件命令
cat /tmp/dentry_chek.log | awk '{print $1"-->"$3}' | sort  | uniq -c | sort  -k1 -n -r| head -n 50

## 分析日志文件輸出結果
  15049 BackgrProcPool[13267]-->d_alloc
  14707 BackgrProcPool[13267]-->d_free
   8367 yum[8606]-->d_alloc
    265 agent_daemon.py[5830]-->d_free
    262 ZooKeeperRecv[13267]-->d_free
    262 ZooKeeperRecv[13267]-->d_alloc
    254 agent[7269]-->d_alloc
    166 clickhouse-serv[13267]-->d_alloc
    162 clickhouse-serv[13267]-->d_free
    131 ZooKeeperSend[13267]-->d_free
    131 ZooKeeperSend[13267]-->d_alloc
    122 agent_daemon.py[5830]-->d_alloc
    114 mysqld[2822]-->d_alloc
    113 mysqld[2822]-->d_free
    107 rdk:b/source[13267]-->d_free
    107 rdk:b/source[13267]-->d_alloc
    105 bash[27747]-->d_free
     89 netstat[8586]-->d_alloc
     62 TCPHandler[13267]-->d_free
     60 irqbalance[3611]-->d_free
     60 irqbalance[3611]-->d_alloc
     58 TCPHandler[13267]-->d_alloc
     56 sh[8578]-->d_free
     55 SystemLogFlush[13267]-->d_alloc
     50 bash[27747]-->d_alloc
     47 snmpd[3679]-->d_free
     47 snmpd[3679]-->d_alloc
     42 netstat[8586]-->d_free
     38 ParalInputsProc[13267]-->d_alloc
     36 ParalInputsProc[13267]-->d_free

從上面的日志分析輸出結果可發現yum進程執行d_alloc的次數遠大於執行d_free的次數。

PS: BackgrProcPool進程的d_alloc與d_free相差較大是由於腳本執行時間點導致。

安裝stap工具

安裝stap工具

## 安裝stap工具
yum install systemtap

stap運行依賴的kernel-devel和kernel-debuginfo,推薦使用stap-prep來安裝。

如果通過yum來安裝kernel-debuginfo,需要開啟debug的yum源,並且嚴格匹配kernel版本,否則很容易報錯或不兼容。

## 下載包:kernel-debuginfo-common-x86_64-xxx.rpm
## 下載包:kernel-debuginfo-xxx.rpm

## centos 7的下載路徑
http://debuginfo.centos.org/7/x86_64/
## ## centos 6的下載路徑
http://debuginfo.centos.org/6/x86_64/

監控進程請求命令

對於周期性執行命令,可以通過watch來監控:

watch -n 1 -d 'ps -ef|grep yum'

參考資料


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM