Linux学习|Gentoo/Arch/FreeBSDLinux学习之路我用 Linux

“内存使用偏高”的一般定位方法

2020-08-13  本文已影响0人  My熊猫眼

简单通用的内存使用偏高排查方法:

1. 以free命令为切入口,查看内存的使用情况(配合vmstat, top, ps,iotop 命令以及proc 的信息):

a. 可用内存是否充足. 判断可用内存的大小,是内存相关问题的首要问题,也是最重要的一个问题,如何尽量减小可用内存的计算误差显的非常重要. 如下的示例显示available memory 有892MB,而这个可用内存的大小通常包含了可以被回收的cache/buff的大小 以及还没有被kernel 管理的内存大小. 一般都认为可用内存的大小就是:free + buff/cache。 但是在下例中可以看到,实际的可用内存小于free + buff/cache, 并且结果中多出了一个叫作shared的值;这之间涉及到的内存使用计算很复杂,鄙人不才,只讨论这个新出现的shared的值对 available 内存的影响:
上述可用内存小于 free+buff/cache ,其中shared的值也为上述的偏差做了一定的贡献,shared的内存中被使用的部分划入了buff/cache的分类,而这些已经使用的shared的内存无法被回收使用,因此 可用内存的计算应该是: free + buff/cache- shared-others unreclaim memory . 而shared内存中没有被使用的部分,那么自然就属于 可以被回收使用的了,也就是可以计入 可用内存范畴的.

[root@localhost vm]# free -m #可用内存=760+232-32-other unreclaimable=809, ohter unreclaim=151M
              total        used        free      shared  buff/cache   available
Mem:           1819         825         760          32         232         809
Swap:             0           0           0
[root@localhost vm]# 

为了验证上述的结果,创建了两个tmpfs 类型的文件系统,并分别写入了177M,194M的数据,看下面的结果:

[root@localhost ~]# df -hT -t tmpfs          #从这里可以看到shared usage=188, 但是系统中还有其他shared的memory, 并不只是单纯的tmpfs 用的,所以这个值小于下面的209MB. 其他shared usage=209-188=21MB
Filesystem     Type   Size  Used Avail Use% Mounted on
tmpfs          tmpfs  910M     0  910M   0% /dev/shm
tmpfs          tmpfs  910M   11M  900M   2% /run
tmpfs          tmpfs  910M     0  910M   0% /sys/fs/cgroup
tmpfs          tmpfs  182M   28K  182M   1% /run/user/1000
tmpfs          tmpfs  512M  177M  336M  35% /mnt/1
tmpfs          tmpfs  512M     0  512M   0% /mnt/2
[root@localhost ~]# free -m         #可用内存= 78+968-209-unreclaimable(151)=686M, 和下面显示的available 基本相等;
              total        used        free      shared  buff/cache   available
Mem:           1819         771          78         209         968         691
Swap:             0           0           0
[root@localhost ~]# cp /sbin/* /mnt/2/
[root@localhost ~]# df -hT -t tmpfs     #shared usage=194+177+11+other shared (21MB)=403MB。 和free 显示的结果基本吻合.
Filesystem     Type   Size  Used Avail Use% Mounted on
tmpfs          tmpfs  910M     0  910M   0% /dev/shm
tmpfs          tmpfs  910M   11M  900M   2% /run
tmpfs          tmpfs  910M     0  910M   0% /sys/fs/cgroup
tmpfs          tmpfs  182M   28K  182M   1% /run/user/1000
tmpfs          tmpfs  512M  177M  336M  35% /mnt/1
tmpfs          tmpfs  512M  194M  319M  38% /mnt/2
[root@localhost ~]# free -m  #可用内存=70+969-403-other unreclaimable(151)=485MB, 和下面显示的结果基本吻合。
              total        used        free      shared  buff/cache   available
Mem:           1819         779          70         402         969         489
Swap:             0           0           0

b. 是否有用到swap空间. 如果有用到swap空间,那么要用”vmstat <interval> <count>“ 这种方式观察 “si 以及so” 的动态变化,如果si/so的值是0,而仅仅是有swap的used value,那么表示曾经出现过换出/换入内存数据 到swap 空间的情况,而目前并没有发生这种状况;
如果si,so的值不为0,并且持续不为0,那么表示当前正在发生swap in 以及swap out 的情况,也就是说 当前有进程需要的内存空间无法直接得到满足(即便通过release 可以释放的cache 依然无法获得满足),需要通过swap 交换来满足,此时可以通过 iotop 命令,依照 swap in 进行排序(iotop 命令可以使用左右键切换排序的关键字),就可以轻松知道哪个进程正在 交换数据到物理内存空间. 通常这会导致性能问题.
没有iotop的命令的情况下,我们可以自己统计 当前进程使用的swap 空间,然后通过采样的方式计算swap in 以及swap out. 只是比较麻烦,具体的数据来源于:/proc/<PID>/smaps,统计使用的swap用命令:cat /proc/<PID>/smaps | grep Swap | awk '{s+=$2};END{print s/1024}', 单位是MB. 不过依然建议使用iotop ,毕竟更方便.

   Swap
       si: Amount of memory swapped in from disk (/s).
       so: Amount of memory swapped to disk (/s).

c. 在上述free结果中的used 确实比较高的情况下,首先验证所有进程占用的内存之和,以下是一个简单的粗略计算:

[root@localhost proc]# ps -eo rsz  | awk '{s+=$0};END{print s/1024,MB}'
1168.29
[root@localhost proc]#

上述的结果大于process 真正占用的memory 大小,这是因为上述统计中,对于shared moudle 统计了多次造成的 。所以计算结果大于实际值. 在这种used 值比较高的情况下,我们一般都需要查看是哪个进程占用了比较多的内存资源,这时候可以用top命令. 在top命令的结果中,按‘f’键,然后选择%mem 作为排序的参考, 查看进程的内存使用情况. 从而找到使用内存比较高的进程。 针对占用内存比较高的进程,要具体分析,看是否属于正常的业务负载造成, 或者是否对应的进程存在内存泄漏的问题.如果不使用top 命令,也可以通过ps命令获得物理内存使用排序:

[root@localhost ~]#  ps -eo rsz,pid,ppid,comm | sort -k1n   | tail
17616  10785      1 evolution-addre
18184  10746  10678 evolution-calen
22752   1200      1 libvirtd
25984  10683      1 vmtoolsd
27112  10455      1 goa-daemon
28080  10647  10161 nautilus-deskto
29540    872      1 firewalld
49444   9823   9816 X
64064  10706  10161 gnome-software
184424 10367  10161 gnome-shell

2. 内存黑洞问题:

linux中有部分内存是通过alloc_pages这种方式直接申请的,此种情况下申请的内存在/proc/meminfo 中并没有记录,所以这种情况会导致“内存黑洞”,也就是看不到内存被用到哪里了,但是确实是被使用了,要弄明白这点,判断是否有内存黑洞,那么直接计算系统中所有进程使用的内存总和 ,与 free报告的used 的值做比较,如果进程使用的所有rs 内存总和远远小于report的used 的内存,那么就是存在内存黑洞:

[root@localhost vm]#  ps -eo rsz  | awk '{s+=$0};END{print s/1024,MB}'       #计算出的进程所用内存总和 ,因为对于share lib 计算了多次,所以实际使用要小于这个值
1262.28 
[root@localhost vm]# free -m        #报告的used ,这个值小于上述计算的值属于正常,如果大于,那么表示有内存黑洞。
              total        used        free      shared  buff/cache   available
Mem:           1819         775         816          40         227         860
Swap:             0           0           0
[root@localhost vm]# 

产生内存黑洞的典型原因:
vmware/kvm 等虚拟机的ballon 驱动通过alloc_pages 申请内存导致的.对于此种情况,那么我们可以通过卸载对应驱动(rmmod命令)来验证,当卸载相应的ballon 驱动,那么消失的内存就回来了.

3. 网络连接问题导致内存被耗尽

当网络连接的队列有大量的Recv-Q和Send-Q 数据包,那么也可能导致内存被消耗掉,这种情况其实通过查找使用内存比较高的进程应该可以找得到,但是可能出现情况较多,所以单独列出来。

简单总结:

上面啰里啰唆的说了那么多,可用内存的计算,大致等于:
free + buff/cache - shared - slab - page tables,该方法并不是很准确,应该是一个差不多的值,仅供参考
判断是否有内存黑洞的方法是:
ps -eo rsz | awk '{s+=$0};END{print s/1024,MB}' 计算所有进程占用的内存值(这个值比实际值要大),然后看free报告的used 的值,如果used 的值大于计算出来的值,那么就有内存黑洞.

本文原创,转载请注明出处

上一篇下一篇

猜你喜欢

热点阅读