zoukankan      html  css  js  c++  java
  • 转载:Linux Used内存到底到哪里去了?

    转自: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操作系统内存分区

    图中内存总共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这份工具,它对内存的使用显示比较直观:

    nmon

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

    top

    通常我们会看进程的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的内存统计表:

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

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

    $slabtop
    

    可以看到

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

    $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
    " `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等共享的模块,在前面的计算中我们重复计算了。

  • 相关阅读:
    anltr 解析MYSQL
    MYSQL 主从复制
    Java happens-before
    傅里叶分析-数据通信的理论基础
    Java jdk常用工具集合
    kafka报错 日志压缩报错直接退出
    linux centos7开启防火墙端口
    mysql_取分组后的前几行值
    数据库隔离级别
    mysql删除重复数据
  • 原文地址:https://www.cnblogs.com/xianzhedeyu/p/5548772.html
Copyright © 2011-2022 走看看