记录一次虚拟机内存黑洞的追查过程

12 篇文章 0 订阅

最近将一台开发机迁移到了虚拟机上,运维同事给的配置跟之前一样,64G内存,可是同事用着没几天就感觉很卡,之前物理机的时候没出现过这个问题。先记录下追查过程

1.free -m和top都查看了当前内存使用情况

# free -m
              total        used        free      shared  buff/cache   available
Mem:          62815       33918       27024          16        1872       28366
Swap:          4095           0        4095          4095           0        4095

# top
top - 18:12:22 up 2 days, 21:16,  6 users,  load average: 1.12, 0.73, 0.69
Tasks: 339 total,   1 running, 338 sleeping,   0 stopped,   0 zombie
%Cpu(s):  2.4 us,  1.0 sy,  0.0 ni, 96.2 id,  0.2 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 64323240 total, 27578116 free, 34827600 used,  1917524 buff/cache
KiB Swap:  4194300 total,  4194300 free,        0 used. 28952176 avail Mem

这里看到差不多使用了35G

2.统计top中进程的res字段,汇总可见的内存使用数,也可以直接查看/proc/pid/smaps

####### get_res.awk start
{
  if(NR >= 8)  
  {
    start = index($6, "g"); 

    if(start != 0)
    {   
      val = substr($6, 0, start -1) * 1024 * 1024; 
      mem_sum += val;
      print $6, substr($6, 0, start -1);
    }   
    else
    {   
      val = $6; 
      mem_sum += val;
    }   
  }
}

END{ printf("%d\n", mem_sum); }
####### end 

# top -b -n 1 | awk -f /tmp/get_res.awk 
5821396

# grep Pss /proc/[1-9]*/smaps | awk '{total+=$2}; END {print total}'
5583365

可以看到,可见的内存使用数也就6G不到,这中间相差了接近30G

3.查看free和top源码,寻找数据来源(procps-ng / procps · GitLab)

# grep MEMINFO_MEM_USED -R . -n
./proc/meminfo.h:92:    MEMINFO_MEM_USED,              //   ul_int        derived from MEM_TOTAL - MEM_BUFFERS - MEM_CACHED_ALL - MEM_FREE
./top/top.c:265:   MEMINFO_MEM_FREE,       MEMINFO_MEM_USED,    MEMINFO_MEM_TOTAL,
./free.c:348:           printf(" %11s", scale_size(MEMINFO_GET(mem_info, MEMINFO_MEM_USED, ul_int), flags, args));
./free.c:394:                               MEMINFO_GET(mem_info, MEMINFO_MEM_USED, ul_int) +
./vmstat.c:203:    MEMINFO_MEM_USED,

略去代码部分,可以看到used这个字段是从/proc/meminfo中获得的,计算过程如下

MEMINFO_MEM_CACHED_ALL,        //   ul_int        derived from MEM_CACHED + MEM_SLAB_RECLAIM
MEMINFO_MEM_USED,              //   ul_int        derived from MEM_TOTAL - MEM_BUFFERS - MEM_CACHED_ALL - MEM_FREE

可见used是一个从其他字段推导出来的值,total,buffers,cache,free这几项是有确定的统计值的

4.详细了解 /pro/meminfo/proc/meminfo之谜 | Linux Performance

内存黑洞

追踪Linux系统的内存使用一直是个难题,很多人试着把能想到的各种内存消耗都加在一起,kernel text、kernel modules、buffer、cache、slab、page table、process RSS…等等,却总是与物理内存的大小对不上,这是为什么呢?因为Linux kernel并没有滴水不漏地统计所有的内存分配,kernel动态分配的内存中就有一部分没有计入/proc/meminfo中。

我们知道,Kernel的动态内存分配通过以下几种接口:

  • alloc_pages/__get_free_page: 以页为单位分配
  • vmalloc: 以字节为单位分配虚拟地址连续的内存块
  • slab allocator
    • kmalloc: 以字节为单位分配物理地址连续的内存块,它是以slab为基础的,使用slab层的general caches — 大小为2^n,名称是kmalloc-32、kmalloc-64等(在老kernel上的名称是size-32、size-64等)。

通过slab层分配的内存会被精确统计,可以参见/proc/meminfo中的slab/SReclaimable/SUnreclaim;

通过vmalloc分配的内存也有统计,参见/proc/meminfo中的VmallocUsed 和 /proc/vmallocinfo(下节中还有详述);

而通过alloc_pages分配的内存不会自动统计,除非调用alloc_pages的内核模块或驱动程序主动进行统计,否则我们只能看到free memory减少了,但从/proc/meminfo中看不出它们具体用到哪里去了。比如在VMware guest上有一个常见问题,就是VMWare ESX宿主机会通过guest上的Balloon driver(vmware_balloon module)占用guest的内存,有时占用得太多会导致guest无内存可用,这时去检查guest的/proc/meminfo只看见MemFree很少、但看不出内存的去向,原因就是Balloon driver通过alloc_pages分配内存,没有在/proc/meminfo中留下统计值,所以很难追踪。

5.验证

# lsmod |grep balloon
vmw_balloon            18094  0 

证明的确有balloon driver在,当前不敢直接rmmod,要等运维同事确认

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值