• 转一篇Linux可用内存的统计方法


    背景
    由于Linux缓存机制的设计,系统对缓存的使用是非常狠的,所以经常会看到某些环境内存只剩几十兆了,而应用只用了不到一半。所以在计算可用内存的时候,一定要算上缓存的部分。
    通常方法,就是通过free命令首行free+cached+buffers计算,或者直接使用第二行的free字段。但这个方法有时仍然会造成比较大的误差,导致性能监控等方面的问题。
    比如系统中使用了大量的共享内存会造成多计算可用内存;再比如对大量的文件做了查询(find / ?!!!
    ),会导致少计算可用内存。对于这点我在《说说free命令》中有详细的说明。这里就不再赘述了。

    SUSE11 SP1基于2.6.32内核,内核暴露了更多的统计接口给用户空间,把slab分为可回收和不可回收两类指标来统计。free命令也对应做了修改。解决了free命令少计算可用内存的问题。但多计算的问题还是存在。
    因此,在这里对统计可用内存的方法做了个总结。供需要的同学参考。(后面有空可能会开发一个统计工具)
    其中SUSE10由于内核版本过低(2.6.16)暴露信息不足,下面的方法仍然不能很精确,但相比通过free命令简单统计而言,一般不会造成比较大的误差。

    可用内存定义
    包括未被使用的空闲内存,以及已经被使用但用作缓存可以自动回收的部分。

    SUSE 10
    可用内存统计方法
    总内存free命令首行total字段。
    空闲内存free命令首行free字段。
    缓存free命令首行buffers字段+cached字段。
    修正值1cached字段包含了共享内存和tmpfs内存文件系统占用的内存。需要减去这两部分。这两部分内存可通过ipcs -m -udf 命令获取。
    修正值2cached字段漏掉了内核slab中可以自动回收的内存,比如xxx_inode_cachedentry_cache。这两部分的内存的计算方法是解析/proc/slabinfo
    最终的可用内存计算方法:
    空闲内存+缓存-修正值1+修正值2

    SUSE 11
    可用内存统计方法
    总内存free命令首行total字段。
    空闲内存free命令首行free字段。
    缓存free命令首行buffers字段+cached字段。
    修正值1cached字段包含了共享内存和tmpfs内存文件系统占用的内存。需要减去这两部分。这两部分内存之和可通过/proc/meminfoShmem字段直接获取。
    最终的可用内存计算方法:
    空闲内存+缓存-修正值1

    1ipcs获取共享内存占用物理内存大小
    # ipcs -m -u
    ------ Shared Memory Status --------
    segments allocated 4
    pages allocated 786433
    pages resident 2 #使用这个字段,单位是页,X86下一个页是4kB
    pages swapped 0
    Swap performance: 0 attempts 0 successes

    2df获取tmpfs占用物理内存大小
    # df
    Filesystem 1K-blocks Used Available Use% Mounted on
    /dev/sda2 20972152 4427900 16544252 22% /
    devtmpfs 24711780 160 24711620 1% /dev #Used字段表示实际占用物理内存
    tmpfs 24711780 0 24711780 0% /dev/shm #Used字段表示实际占用物理内存
    /dev/sda5 1052184 59188 992996 6% /boot
    /dev/sda9 83888824 16852500 67036324 21% /iso
    /dev/sda7 10490040 1142876 9347164 11% /opt
    /dev/sda10 83888824 9421200 74467624 12% /src
    /dev/sda8 20972152 3475104 17497048 17% /usr
    /dev/sda6 5245016 328392 4916624 7% /var


    ///////////////////增加统计工具////////2011.6.29///////////////////////////////////////////////////
    统计工具(SUSE10SUSE11验证通过)
    1.
    修正可用内存多计算的情况(SUSE10 SUSE11
    如下环境,在进行了大量共享内存创建使用后,free命令统计可用内存,出现了很大的误差。
    #echo 3 >/proc/sys/vm/drop_caches #清理可回收的内存
    # free
    total used free shared buffers cached
    Mem: 49423560 13609680 35813880 0 26764
    11686608 #仍有11G不可以回收,因为是共享内存,不具备回收属性。
    -/+ buffers/cache: 1896308
    47527252 # free计算可用内存,算入了共享内存,得到47G
    Swap: 2104472 0 2104472
    # ipcs -m -u
    ------ Shared Memory Status --------
    segments allocated 20
    pages allocated 4980737
    pages resident 2883591 #共享内存有2883591 * 4 = 11534364 kB ~= 11G
    pages swapped 0
    Swap performance: 0 attempts 0 successes
    # afree
    Total: 49423560 kB #
    物理内存总计
    Free: 35816908 kB #
    未被使用的内存
    Reclaimable: 179348 kB #
    被使用了但是可以自动回收的内存
    Available: 35996256 kB #afree统计出来的可用内存去除了11G的共享内存。

    2.
    修正可用内存少计算的情况(SUSE10
    如下环境,在进行了大量文件访问操作后,系统中缓存了大概600Minodedentry
    # free
    total used free shared buffers cached
    Mem: 3987316 1080908 2906408 0 163056 163848
    -/+ buffers/cache: 754004
    3233312 #没有统计slab中的可以回收的inodedentry
    Swap: 2104472 0 2104472
    # afree
    Total: 3987316 kB
    Free: 2906384 kB
    Reclaimable: 958888 kB
    Available:
    3865272 kB #afree统计了slab中的可以回收的inodedentry
    # echo 3 >/proc/sys/vm/drop_caches #释放600Minodedentry缓存。
    # free
    total used free shared buffers cached
    Mem: 3987316 93628 3893688 0 17780 8948
    -/+ buffers/cache: 66900
    3920416 #执行drop_caches后,增加了600M,说明cached少统计了可回收的slab缓存。这600M即使不执行drop_caches也都是可用的,系统在需要的时候会自动回收。

    注:afree通过解析slabinfo文件统计可回收的slab,其实suse10的内核有一个全局变量slab_reclaim_pages维护了准确的可回收数量,但没有暴露给给用户空间,因此更准确的方法其实就是写一个模块,把这个变量导出到来。

    afree代码如下:

    #!/bin/sh
    #
    #Get accurate available memory.
    #

    function get_meminfo()
    {
       grep -w $1 /proc/meminfo | awk -F' ' '{print $2}'
    }
    function show_meminfo()
    {
       printf "%s\t%10d kB\n" "$1" "$2"
    }

    PAGE_SIZE=4 #kB, for x86
    function get_shmem_from_ipcs()
    {
       local _shm=0
       _shm=$(ipcs -m -u | grep 'pages resident' | awk -F' ' '{print $3}')
       echo $((_shm * PAGE_SIZE))
    }
    function get_tmpfs_from_df()
    {
       local _size=""
       _size=$(df -k | awk -F' ' 'BEGIN{total=0} {if ($1 == "tmpfs" || $1 == "devtmpfs" || $1 == "shm")total+=$3}END{print total}')
       echo $_size 
    }

    #inode, dentry and buffer_head is reclaimable
    function get_slab_reclaimable_from_slabinfo()
    {
       local _size=""
       _size=$(awk -F' ' 'BEGIN{total=0} {if ($1~/inode/ || $1~"dentry" || $1 == "buffer_head")total+=($3 * $4)}END{printf "%d\n", total / 1024}' /proc/slabinfo)
       [ -z "$_size" ] && _size=0
       echo $_size 
    }

    free=$(get_meminfo MemFree)
    total=$(get_meminfo MemTotal) 
    cached=$(get_meminfo Cached)
    buffer=$(get_meminfo Buffers)
    swapcached=$(get_meminfo SwapCached)
    shmem=$(get_meminfo Shmem)
    slab_reclaimable=$(get_meminfo SReclaimable)
    nfs_unstable=$(get_meminfo NFS_Unstable)

    #the kernel does not support, no 'Shmem' field in /proc/meminfo, we use ipc and df.
    if [ -z "$shmem" ] ; then
       shmem=$(( $(get_shmem_from_ipcs) + $(get_tmpfs_from_df) ))
    fi

    #the kernel does not support, no 'SReclaimable' field in /proc/meminfo, we use /proc/slabinfo.
    if [ -z "$slab_reclaimable" ]; then
       slab_reclaimable=$(get_slab_reclaimable_from_slabinfo)
    fi

    #the kernel does not support, no 'NFS_Unstable' field in /proc/meminfo, we use null. :)
    if [ -z "$nfs_unstable" ]; then 
       nfs_unstable=0
    fi


    reclaimable=$((cached + buffer + slab_reclaimable + swapcached + nfs_unstable - shmem))
    available=$((free + reclaimable))
    show_meminfo "Total: "       

    说说free命令

    free是个常用命令,几乎每个接触、使用linux的用户都会用到它。但往往对它的统计输出会有一些困惑,这一方面和Linux内存管理机制有关,另一方面Linux在内存统计上也确实有些不足和问题。

    关键在于两个字段,buffers和cached。

    你经常会发现Linux系统用了一段时间后,内存所剩无几,free命令,一看,内存全跑到 buffers和cached里面了;这个现象是正常的。访问过的磁盘文件的元数据及内容,内核都会缓存起来。这些缓存就是磁盘缓存。

    Linux磁盘缓存设计特点(设计理念):
    除了系统运行必须的一小部分保留外,只要有剩余内存,只要需要,就会用给磁盘缓存。(没有一个参数可以让你限定缓存的上限。2.6内核之前有一个限定参数,后来给取消了)

    所以会经常看到内存所剩无几的现象,这是缓存机制导致的,对应用是透明,在有内存需要时,这些内存会释放。这个过程对应用是透明的,应用可以认为系统的可用内存包括buffers和cached。


    这种设计,在大多数服务器应用场景下都有比较好的性能表现。可以说是比较可取的。

    设计本身没有问题,但free命令显示的buffers和cached并不能和磁盘缓存完全对应,这是实现细节上的不足和问题。


    1. buffers和cached包含了不属于磁盘缓存的内容。
    由于buffers和cached实际上就是内核为所有文件映射分配的物理页的总和(page cache)。
    但内核中的“文件概念”是广泛的,不仅包含了真正位于磁盘上的文件,还包含了为特殊需要创建的虚拟文件,比如:

    进程间的共享内存(通过shmget API创建的内存),内核建立一个虚拟的文件和共享内存关联起来。(通过pmap命令你可以看到进程拥有的共享内存地址空间的映射字段是/SYSVXXXX字样,不是匿名的)。

    非常的不幸,这些虚拟文件映射关联的page,也被算入了free命令显示的cached字段。但这部分内存没有缓存属性,在内存不足时不能按缓存的方式来回收。(使用echo 3 >/proc/sys/vm/drop_caches,无法释放掉这部分内存)

    这个问题,会带来一些麻烦。比如,按照常规理解,某产品设计内存占用过高告警的条件是,空闲内存+buffers+cached小于内存总和的20% 。一般情况下没有问题,但如果产品使用了大量的共享内存,告警将失去作用。

    2. buffers和cached遗漏了部分属于磁盘缓存的内容。
    还 是由于buffers和cached只是内核为所有文件映射分配的物理页的总和。在文件系统方面,还有一部分缓存是不和文件映射相关联的,比如内核分配的 inode对象,在文件关闭时,并不会立即释放,具备缓存的属性。这部分不在基于文件映射的页面里,而是通过slab(内核内存池)分配的。

    原文:http://yalung929.blog.163.com/blog/static/203898225201223102617451/

  • 相关阅读:
    OJ生成器(一)制作Online Judge前的准备和策划
    中国剩余定理
    图片
    扩展GCD的一点心得
    用css控制连续英文字符或数字换行
    CTFHUB HTTP协议之请求方式
    PHP基础05---文件处理
    PHP基础04---文件包含
    PHP基础03---数组
    PHP基础01
  • 原文地址:https://www.cnblogs.com/feisky/p/2447503.html
Copyright © 2020-2023  润新知