Linux下内存使用分析思路
在系统层面最基础最重要的三个指标是CPU、IO、memory,本篇主要汇总定位分析内存使用的常见思路。在进行下一步之前,需要先对top、free 、/proc/meminfo、slabtop、nmon等工具要有一个概念和认识。如果可能的话,最好还需要先了解下/proc/$pid下的smaps和status文件。以下为定位内存被谁占用的常见思路。
一、free和top
free命令是linux的一个入门级命令,显示的是一个比较总述性的信息,如下:
1[root@361way ~]# free -m
2 total used free shared buffers cached
3Mem: 995 874 121 0 105 249
4-/+ buffers/cache: 518 477
5Swap: 0 0 0
比如上面的输出中,我们大致可以看到我总内存为1G(995,其中hardward和firmware在启动时会预先占用一点)。其中已使用874M ,其中可用121M,buffers和cached加用的量为105M + 249M ,这里需要注意的是平时我们在查看时,一般会以第二行的结果为准,即实际可用477M,已用518M。为什么这样说?因为buffers和cached是为了加快运算速度,会预占用一部分内存,可以理解为缓存的概念。由于这部分不是本篇的重点,想深究的可以找谷歌。这部分内存可以通过如下的命令进行回收:
1To free pagecache:
2echo 1 > /proc/sys/vm/drop_caches
3To free dentries and inodes:
4echo 2 > /proc/sys/vm/drop_caches
5To free pagecache, dentries and inodes:
6echo 3 > /proc/sys/vm/drop_caches
在有业务运行的情况下,强烈不建议这样操作,因为可能会造成数据丢失。即然内存被使用,到底被谁占去了呢?可以借助强大的top查看。
如上图所示,在top下我们输入大M就可以按内存使用率排序。上面可以看到我内存主要被hhvm进程占用掉了,占比总内存的34.3% 。可以看到,实际上top上面也有free的功能,对memory会有概述性报告的。其中RES是我们要关注的项,即实际该进程占用的内存量,基本上这样我们就定位到内存用到那去了。现网中经常还需要一种情况,top看到的所有进程的RES使用都不大,而内存一下子少了几十G,这个怎么破呢?看下面。
二、nmon 、/proc/meminfo 与slabtop
1、/proc/meminfo
meminfo文件显示出的也是内存的概述性信息,只不过其比free -m的结果要更详细,如下:
1[root@361way ~]# cat /proc/meminfo
2MemTotal: 1019644 kB 所有可用RAM大小 (即物理内存减去一些预留位和内核的二进
3制代码大小)
4MemFree: 119464 kB LowFree与HighFree的总和,被系统留着未使用的内存
5Buffers: 110680 kB 用来给文件做缓冲大小
6Cached: 256796 kB 被高速缓冲存储器(cache memory)用的内存的大小(等于
7diskcache + SwapCache )
8SwapCached: 0 kB
9Active: 680560 kB 在活跃使用中的缓冲或高速缓冲存储器页面文件的大小,除非
10非常必要否则不会被移作他用
11Inactive: 145228 kB 在不经常使用中的缓冲或高速缓冲存储器页面文件的大小,可
12能被用于其他途径
13Active(anon): 458208 kB
14Inactive(anon): 280 kB
15Active(file): 222352 kB
16Inactive(file): 144948 kB
17Unevictable: 0 kB
18Mlocked: 0 kB
19SwapTotal: 0 kB
20SwapFree: 0 kB
21Dirty: 92 kB 等待被写回到磁盘的内存大小
22Writeback: 0 kB 正在被写回到磁盘的内存大小
23AnonPages: 458328 kB 未映射页的内存大小
24Mapped: 27072 kB 设备和文件等映射的大小
25Shmem: 176 kB
26Slab: 53564 kB 内核数据结构缓存的大小,可以减少申请和释放内存带来的消耗
27SReclaimable: 32404 kB 可收回Slab的大小
28SUnreclaim: 21160 kB 不可收回Slab的大小(SUnreclaim+SReclaimable=Slab)
29KernelStack: 1136 kB 内核栈大小占用的内存
30PageTables: 5856 kB 管理内存分页页面的索引表的大小
31NFS_Unstable: 0 kB 不稳定页表的大小
32Bounce: 0 kB
33WritebackTmp: 0 kB
34CommitLimit: 509820 kB
35Committed_AS: 1483868 kB
36VmallocTotal: 34359738367 kB 可以vmalloc虚拟内存大小
37VmallocUsed: 7472 kB 已经被使用的虚拟内存大小
38VmallocChunk: 34359728764 kB
39HardwareCorrupted: 0 kB
40AnonHugePages: 198656 kB
41HugePages_Total: 0
42HugePages_Free: 0
43HugePages_Rsvd: 0
44HugePages_Surp: 0
45Hugepagesize: 2048 kB
46DirectMap4k: 7168 kB
47DirectMap2M: 1044480 kB
可以看到上面的内存具体用途显示的特别详细,有点像饭店或超市的帐单。其中有几个我们经常接触到的有buffer 、cached 、slab、hugepage、vmall 。前两者就不说了,slab后面也会单独提到,hugepage是为了加快IO处理的速度设置的一个调优项,在数据库、虚拟化上经常会调节该部分,也会出现该部分占用较大的情况。vmall 是一个些许专业的概念,具体可以参看百科、csdn上的介绍。该值我们可以在内核启动时vmalloc=xxx来指定。由于这部分显示的要远大于物理内存,平时我们时关注VmallocUsed一项即可。
所以针对上面提到的进程本身占用都不多,而free -m 确发现已用几十G的情况,就可以在这里查看到具体是那一项占的高,很可能是hugepage或slab 。
2、nmon
/proc/meminfo显示的结果非常详细也非常直观,不过我们平时关心的主要就那几个,而且显示如此多,很多一些重要的东西就忽略掉了,这里可以借助IBM出的工具nmon来查看内存分配情况。如下图:
从上面这个输出,也可以看到主要内存还是被active占用的。其次是cached和buffers 。其他几块并没有占用多少内存。
注意:SecureCRT下nmon会有乱码出现,通过将终端类型修改为vt100并重连就OK了。
3、slabtop
内核的模块在分配资源的时候,为了提高效率和资源的利用率,都是透过slab来分配的。slab为结构性缓存占用内存,该项也经常占用很大的内存。不过借助slabtop工具,我们可以很方便的显示内核片缓存信息,该工具可以更直观的显示/proc/slabinfo下的内容。理解意思就行,如下图:
如上图所示,objs是指对象的个数,obj_size为对象的大小,use是使用的百分比,这个百分比是针对后面的cache_size来说的。cache_size是给kmem_cache所有对象分配的总大小。我们可以将slabtop查看到的结果与/proc/slabinfo的结果做一个对比,如下,其中/proc/slabinfo中的第三列与第四列的值为num_objs和objsize。这里通过slabtop取得的cache_size乘百分比得到的结果和/proc/slabinfo 3、4列乘积求和得到的结果基本相同。
1[root@361way 01]# slabtop -o|column -t|grep ^[0-9]|awk 'BEGIN{sum=0;}{sum=sum+int($(NF-1)*int($3));}END{print sum/1024/100}'
249.4671
3[root@361way 01]# cat /proc/slabinfo |awk 'BEGIN{sum=0;}{sum=sum+$3*$4;}END{print sum/1024/1024}'
451.9877
同样,在对slabtop不乘百分比时求和与/proc/meminfo里slab项得到的值也基本相同:
1[root@361way 01]# slabtop -o|column -t|grep ^[0-9]|awk 'BEGIN{sum=0;}{sum=sum+int($(NF-1));}END{print sum/1024}'
254.0898
所以我们也可以通过/proc/slabinfo获取占用内存大于100M的对象集:
1# cat /proc/slabinfo |awk '{if($3*$4/1024/1024 > 100){print $1,$3*$4/1024/1024} }'
2 ext3_inode_cache 282.575
3 proc_inode_cache 2154.03
4 dentry_cache 868.075
如上面的结果,可以看到发现proc_inode这个占了2G多。是占比较多的。
三、进程内存及其他
和内存相关的虚拟文件还有如下这些,其中我们比较重点关注的是smaps和status文件,smem工具就是就是根据这些文件进行的统计分析与处理,具体可以参看我的另一篇博文---linux用smem分析内存占用情况 。
1/proc/$pid/cmdline
2/proc/$pid/smaps 详细的内存占用情况
3/proc/$pid/status 详细的内存占用情况
4/proc/$pid/maps
5/proc/$pid/stat
6/proc/meminfo
这里我们以hhvm 程序的内存为例,这两个文件的内容如下:
1[root@361way 01]# cat /proc/22186/smaps |more //内存使用的分类明细
200400000-02335000 r-xp 00000000 ca:01 1073823 /usr/bin/hhvm
3Size: 31956 kB
4Rss: 30496 kB
5Pss: 30494 kB
6Shared_Clean: 4 kB
7Shared_Dirty: 0 kB
8Private_Clean: 30492 kB
9Private_Dirty: 0 kB
10Referenced: 8136 kB
11Anonymous: 0 kB
12AnonHugePages: 0 kB
13Swap: 0 kB
14KernelPageSize: 4 kB
15MMUPageSize: 4 kB
1602534000-025b8000 rwxp 01f34000 ca:01 1073823 /usr/bin/hhvm
17Size: 528 kB
18Rss: 452 kB
19Pss: 450 kB
20Shared_Clean: 4 kB
21Shared_Dirty: 0 kB
22Private_Clean: 364 kB
23Private_Dirty: 84 kB
24Referenced: 100 kB
25Anonymous: 84 kB
26AnonHugePages: 0 kB
27Swap: 0 kB
28KernelPageSize: 4 kB
29MMUPageSize: 4 kB
30025b8000-02603000 rwxp 00000000 00:00 0
31Size: 300 kB
32Rss: 252 kB
33Pss: 252 kB
34Shared_Clean: 0 kB
35Shared_Dirty: 0 kB
36Private_Clean: 0 kB
37Private_Dirty: 252 kB
38Referenced: 164 kB
39Anonymous: 252 kB
40AnonHugePages: 0 kB
41Swap: 0 kB
42KernelPageSize: 4 kB
43MMUPageSize: 4 kB
44029b7000-02c39000 rwxp 01fb7000 ca:01 1073823 /usr/bin/hhvm
45Size: 2568 kB
46Rss: 8 kB
47Pss: 8 kB
48[root@361way 01]# cat /proc/22186/status //本进程的内存使用概述
49Name: hhvm
50State: S (sleeping)
51Tgid: 22186
52Pid: 22186
53PPid: 1
54TracerPid: 0
55Uid: 500 500 500 500
56Gid: 500 500 500 500
57Utrace: 0
58FDSize: 64
59Groups: 500
60VmPeak: 1198068 kB
61VmSize: 1198064 kB
62VmLck: 0 kB
63VmHWM: 369216 kB
64VmRSS: 318504 kB
65VmData: 772992 kB
66VmStk: 88 kB
67VmExe: 31956 kB
68VmLib: 144840 kB
69VmPTE: 1688 kB
70VmSwap: 0 kB
71Threads: 4
72SigQ: 2/7789
73SigPnd: 0000000000000000
74ShdPnd: 0000000000000000
75SigBlk: 0000000000000000
76SigIgn: 0000000000001000
77SigCgt: 0000000182006eed
78CapInh: 0000000000000000
79CapPrm: 0000000001800400
80CapEff: 0000000001800400
81CapBnd: ffffffffffffffff
82Cpus_allowed: 7fff
83Cpus_allowed_list: 0-14
84Mems_allowed: 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001
85Mems_allowed_list: 0
86voluntary_ctxt_switches: 492
87nonvoluntary_ctxt_switches: 194
常见的内存分析手段和工具基本上就上面这些,如果想和更深一步的了解内存在kernel 中的分配原理,可以参看如下内存管理页面:
捐赠本站(Donate)
如您感觉文章有用,可扫码捐赠本站!(If the article useful, you can scan the QR code to donate))
- Author: shisekong
- Link: https://blog.361way.com/memory-analysis/5018.html
- License: This work is under a 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议. Kindly fulfill the requirements of the aforementioned License when adapting or creating a derivative of this work.