转载:Linux Used内存到底到哪里去了?

时间:2024-08-17 23:05:38

转自:http://blogread.cn/it/article/6264?f=wb2

有时在Linux下会碰到这样的问题:ps aux看到的RSS内存只有不到30M,但是free看到内存却已经使用了7、8G了,已经开始swap了,这是怎么回事?

通常我们查看系统内存都是用free命令:

$free -m
total used free shared buffers cached
Mem: 2010 1721 289 7 99 606
-/+ buffers/cache: 1015 995
Swap: 3904 0 3904

如何解读输出的这些信息呢?下面这个图看的挺清楚:

转载:Linux Used内存到底到哪里去了?

图中内存总共4092M,用掉了3270M,其中buffers+cached是36+1482=1518M,这部分内存是可以回收的,如果需要的话,可以释放出来,这样用掉的内存就是3270-1518=1752M,由于会有一部分计算和系统的耗费,这个值是1748M。

释放缓存:

$ 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

或者:

#free -m
total used free shared buffers cached
Mem: 2010 1742 268 8 100 608
-/+ buffers/cache: 1033 976
Swap: 3904 0 3904 #echo 1 > /drop/sys/vm/drop_caches
#free -m
total used free shared buffers cached
Mem: 2010 1204 806 8 0 162
-/+ buffers/cache: 1041 969
Swap: 3904 0 3904

现在清楚了几个概念:

  1. 总的内存是多少
  2. buffer/cache内存可以释放
  3. used内存的概率

下面就要追查以下used的空间到底去哪儿了。

首先介绍nmon这份工具,它对内存的使用显示比较直观:

转载:Linux Used内存到底到哪里去了?

使用的内存的去向我们很自然的就想到操作系统系统上的各种进程需要消耗各种内存,我们透过top工具来看下:

转载:Linux Used内存到底到哪里去了?

通常我们会看进程的RES这一项,这项到底是什么意思呢?这个数字从哪里出来的呢? 通过strace对top和nmon的追踪和结合源码,我们确定这个值是从/proc/PID/statm的第二个字段读取出来的.

    /proc/[pid]/statm
Provides information about memory usage, measured in pages. The
columns are:
size total program size
(same as VmSize in /proc/[pid]/status)
resident resident set size
(same as VmRSS in /proc/[pid]/status)
share shared pages (from shared mappings)
text text (code)
lib library (unused in Linux 2.6)
data data + stack
dt dirty pages (unused in Linux 2.6)

resident set size 也就是每个进程用了具体的多少页的内存。由于linux系统采用的是虚拟内存,进程的代码,库,堆和栈使用的内存都会消耗内存,但是申请出来的内存,只要没真正touch过,是不算的,因为没有真正为之分配物理页面。

我们实际进程使用的物理页面应该用resident set size来算的,遍历所有的进程,就可以知道所有的所有的进程使用的内存。

实验RSS的使用情况:

#! /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"

从数字来看,我们的进程使用了大概7024M内存,距离7637M还有几百M内存哪里去了? 哪里去了?

仔细看一下nmon的内存统计表:

转载:Linux Used内存到底到哪里去了?

slab又是什么?PageTable又是什么?

简单的说内核为了高性能每个需要重复使用的对象都会有个池,这个slab池会cache大量常用的对象,所以会消耗大量的内存。运行命令:

$slabtop

可以看到

转载:Linux Used内存到底到哪里去了?

虽然没有给出,但给出了具体情况,可以自己算:

$echo `cat /proc/slabinfo | awk 'BEGIN{sum=0;} {sum=sum+$3*$4;}END{print sum/1024/1024}'`MB
904.256 MB

PageTables呢?

struct page是系统boot的时候就会根据内存大小算出来分配出去的,18内核是1.56%左右,32内核由于cgroup的原因会在2.3%

$echo `grep PageTables /proc/meminfo | awk '{print $2}'` KB
58052 KB

小结

内存的去向主要有3个:

  1. 进程消耗
  2. slab消耗
  3. pagetable消耗

汇总一下:

#/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。

我们重新校对下我们的计算。 我们和nmon来比对下,slab和pagetable的值是吻合的。 那最大的问题可能在进程的消耗计算上。

resident resident set size 包括我们使用的各种库和so等共享的模块,在前面的计算中我们重复计算了。