Linux下内存使用分析思路

2015年1月11日 发表评论 阅读评论

在系统层面最基础最重要的三个指标是CPU、IO、memory,本篇主要汇总定位分析内存使用的常见思路。在进行下一步之前,需要先对top、free 、/proc/meminfo、slabtop、nmon等工具要有一个概念和认识。如果可能的话,最好还需要先了解下/proc/$pid下的smaps和status文件。以下为定位内存被谁占用的常见思路。

一、free和top

free命令是linux的一个入门级命令,显示的是一个比较总述性的信息,如下:

[root@361way ~]# free -m
             total       used       free     shared    buffers     cached
Mem:           995        874        121          0        105        249
-/+ buffers/cache:        518        477
Swap:            0          0          0

比如上面的输出中,我们大致可以看到我总内存为1G(995,其中hardward和firmware在启动时会预先占用一点)。其中已使用874M ,其中可用121M,buffers和cached加用的量为105M + 249M ,这里需要注意的是平时我们在查看时,一般会以第二行的结果为准,即实际可用477M,已用518M。为什么这样说?因为buffers和cached是为了加快运算速度,会预占用一部分内存,可以理解为缓存的概念。由于这部分不是本篇的重点,想深究的可以找谷歌。这部分内存可以通过如下的命令进行回收:

To free pagecache:
echo 1 > /proc/sys/vm/drop_caches
To free dentries and inodes:
echo 2 > /proc/sys/vm/drop_caches
To free pagecache, dentries and inodes:
echo 3 > /proc/sys/vm/drop_caches

在有业务运行的情况下,强烈不建议这样操作,因为可能会造成数据丢失

即然内存被使用,到底被谁占去了呢?可以借助强大的top查看。

top memory

如上图所示,在top下我们输入大M就可以按内存使用率排序。上面可以看到我内存主要被hhvm进程占用掉了,占比总内存的34.3% 。可以看到,实际上top上面也有free的功能,对memory会有概述性报告的。其中RES是我们要关注的项,即实际该进程占用的内存量,基本上这样我们就定位到内存用到那去了。现网中经常还需要一种情况,top看到的所有进程的RES使用都不大,而内存一下子少了几十G,这个怎么破呢?看下面。

二、nmon 、/proc/meminfo 与slabtop

1、/proc/meminfo

meminfo文件显示出的也是内存的概述性信息,只不过其比free -m的结果要更详细,如下:

[root@361way ~]# cat /proc/meminfo
MemTotal:        1019644 kB    所有可用RAM大小 (即物理内存减去一些预留位和内核的二进
制代码大小)
MemFree:          119464 kB    LowFree与HighFree的总和,被系统留着未使用的内存
Buffers:          110680 kB    用来给文件做缓冲大小
Cached:           256796 kB    被高速缓冲存储器(cache memory)用的内存的大小(等于
diskcache + SwapCache )
SwapCached:            0 kB   
Active:           680560 kB  在活跃使用中的缓冲或高速缓冲存储器页面文件的大小,除非
非常必要否则不会被移作他用
Inactive:         145228 kB    在不经常使用中的缓冲或高速缓冲存储器页面文件的大小,可
能被用于其他途径
Active(anon):     458208 kB
Inactive(anon):      280 kB
Active(file):     222352 kB
Inactive(file):   144948 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:                92 kB   等待被写回到磁盘的内存大小
Writeback:             0 kB   正在被写回到磁盘的内存大小
AnonPages:        458328 kB   未映射页的内存大小
Mapped:            27072 kB   设备和文件等映射的大小
Shmem:               176 kB
Slab:              53564 kB   内核数据结构缓存的大小,可以减少申请和释放内存带来的消耗
SReclaimable:      32404 kB   可收回Slab的大小
SUnreclaim:        21160 kB   不可收回Slab的大小(SUnreclaim+SReclaimable=Slab)
KernelStack:        1136 kB   内核栈大小占用的内存
PageTables:         5856 kB   管理内存分页页面的索引表的大小
NFS_Unstable:          0 kB   不稳定页表的大小
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:      509820 kB
Committed_AS:    1483868 kB
VmallocTotal:   34359738367 kB  可以vmalloc虚拟内存大小
VmallocUsed:        7472 kB     已经被使用的虚拟内存大小
VmallocChunk:   34359728764 kB
HardwareCorrupted:     0 kB
AnonHugePages:    198656 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:        7168 kB
DirectMap2M:     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来查看内存分配情况。如下图:

IBM nmon memory

从上面这个输出,也可以看到主要内存还是被active占用的。其次是cached和buffers 。其他几块并没有占用多少内存。

注意:SecureCRT下nmon会有乱码出现,通过将终端类型修改为vt100并重连就OK了。

3、slabtop

内核的模块在分配资源的时候,为了提高效率和资源的利用率,都是透过slab来分配的。slab为结构性缓存占用内存,该项也经常占用很大的内存。不过借助slabtop工具,我们可以很方便的显示内核片缓存信息,该工具可以更直观的显示/proc/slabinfo下的内容。理解意思就行,如下图:

slabtop memory

如上图所示,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列乘积求和得到的结果基本相同。

[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}'
49.4671
[root@361way 01]# cat /proc/slabinfo |awk 'BEGIN{sum=0;}{sum=sum+$3*$4;}END{print sum/1024/1024}'
51.9877

同样,在对slabtop不乘百分比时求和与/proc/meminfo里slab项得到的值也基本相同:

[root@361way 01]# slabtop -o|column  -t|grep ^[0-9]|awk 'BEGIN{sum=0;}{sum=sum+int($(NF-1));}END{print sum/1024}'
54.0898

所以我们也可以通过/proc/slabinfo获取占用内存大于100M的对象集:

# cat /proc/slabinfo |awk '{if($3*$4/1024/1024 > 100){print $1,$3*$4/1024/1024} }'
 ext3_inode_cache 282.575
 proc_inode_cache 2154.03
 dentry_cache 868.075

如上面的结果,可以看到发现proc_inode这个占了2G多。是占比较多的。

三、进程内存及其他

和内存相关的虚拟文件还有如下这些,其中我们比较重点关注的是smaps和status文件,smem工具就是就是根据这些文件进行的统计分析与处理,具体可以参看我的另一篇博文---linux用smem分析内存占用情况

/proc/$pid/cmdline
/proc/$pid/smaps   详细的内存占用情况
/proc/$pid/status   详细的内存占用情况
/proc/$pid/maps
/proc/$pid/stat
/proc/meminfo

这里我们以hhvm 程序的内存为例,这两个文件的内容如下:

[root@361way 01]# cat /proc/22186/smaps |more     //内存使用的分类明细
00400000-02335000 r-xp 00000000 ca:01 1073823                            /usr/bin/hhvm
Size:              31956 kB
Rss:               30496 kB
Pss:               30494 kB
Shared_Clean:          4 kB
Shared_Dirty:          0 kB
Private_Clean:     30492 kB
Private_Dirty:         0 kB
Referenced:         8136 kB
Anonymous:             0 kB
AnonHugePages:         0 kB
Swap:                  0 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
02534000-025b8000 rwxp 01f34000 ca:01 1073823                            /usr/bin/hhvm
Size:                528 kB
Rss:                 452 kB
Pss:                 450 kB
Shared_Clean:          4 kB
Shared_Dirty:          0 kB
Private_Clean:       364 kB
Private_Dirty:        84 kB
Referenced:          100 kB
Anonymous:            84 kB
AnonHugePages:         0 kB
Swap:                  0 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
025b8000-02603000 rwxp 00000000 00:00 0
Size:                300 kB
Rss:                 252 kB
Pss:                 252 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:       252 kB
Referenced:          164 kB
Anonymous:           252 kB
AnonHugePages:         0 kB
Swap:                  0 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
029b7000-02c39000 rwxp 01fb7000 ca:01 1073823                            /usr/bin/hhvm
Size:               2568 kB
Rss:                   8 kB
Pss:                   8 kB
[root@361way 01]# cat /proc/22186/status      //本进程的内存使用概述
Name:   hhvm
State:  S (sleeping)
Tgid:   22186
Pid:    22186
PPid:   1
TracerPid:      0
Uid:    500     500     500     500
Gid:    500     500     500     500
Utrace: 0
FDSize: 64
Groups: 500
VmPeak:  1198068 kB
VmSize:  1198064 kB
VmLck:         0 kB
VmHWM:    369216 kB
VmRSS:    318504 kB
VmData:   772992 kB
VmStk:        88 kB
VmExe:     31956 kB
VmLib:    144840 kB
VmPTE:      1688 kB
VmSwap:        0 kB
Threads:        4
SigQ:   2/7789
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000001000
SigCgt: 0000000182006eed
CapInh: 0000000000000000
CapPrm: 0000000001800400
CapEff: 0000000001800400
CapBnd: ffffffffffffffff
Cpus_allowed:   7fff
Cpus_allowed_list:      0-14
Mems_allowed:   00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001
Mems_allowed_list:      0
voluntary_ctxt_switches:        492
nonvoluntary_ctxt_switches:     194

常见的内存分析手段和工具基本上就上面这些,如果想和更深一步的了解内存在kernel 中的分配原理,可以参看如下内存管理页面:

Linux Memory Management

Memory Management

Linux 内存管理




本站的发展离不开您的资助,金额随意,欢迎来赏!

You can donate through PayPal.
My paypal id: itybku@139.com
Paypal page: https://www.paypal.me/361way

  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.