Linux MemAvailable构成分析

       在分析Linux系统内存时候,我们经常会通过观察/proc/meminfo的数据。而判断当前系统内存是否紧缺的时候,往往会关注MemFree和MemAvailable两个参数。那么这两个参数的关系是什么呢?谁能表示当前系统的内存紧张程度?
我们先从结构与关系的角度来区分两个参数的含义。MemAvailable的参数通过procfs获取,可以对应内核源码fs/proc/meminfo.c可以看到关键的变量:
meminfo_proc_show
|-->available = si_mem_available()

  

        按图索骥,关于available的计算实现在mm/page_alloc.c。结合代码实现,可以很清晰获取Memavailable的构成以及和MemFree的关系。本文试图抛开源码,通过如下总结的图,展开说明其原理。若对其中实现细节感兴趣的小伙伴,还是建议回到代码本身

 

  

        如上图所示,MemAvailable的构成来自三个部分(注意不是全部):
  • MemFree

  对应/proc/meminfo的MemFree,就是客观上对应的系统可以“直接”分配使用的内存。

  • PageCache

       对应/proc/meminfo的Active(file)+Inactive(file),该部分内存可以通过回收之后分配使用

  • KReclaimable

       对应/proc/meminfo的KReclaimable(包含了SLAB的可回收内存,即SReclaimable),该部分内存也可以通过回收之后分配使用

        至此,我们可知:MemAvailable包含的成分来自MemFree和可回收的内存(PageCache和KReclaimable)。
        那么对每类成分中具体的构成又是怎样呢?
        先看来自MemFree的部分,称其纳入MemAvalaible的部分Available-part1。linux的内存一般包括几个常见的区域(Zone),如Normal Zone, DMA Zone,还有其他Zone(如Device Zone, Movable Zone)。这些Zone的空闲内存的总和,对应的就是MemFree。那么对每个Zone的空闲内存,为了便于理解,我们可以拆分三个部分:lowmem reserve, high wmark, 和free left。
  • lowmem_reserve

        每类Zone其lowmem reserve的大小可能不一样。该类空闲内存是避免跨zone分配内存时被“抢光”的情况。比如Normal Zone的内存分配不足时,会通过DMA Zone进行“借用”,而DMA的lowmem reserve是“家底”,不会被借用出去。

        需要注意的是,不是每个zone都有lowmem reserve(主要是Normal Zone和DMA Zone)。其计算方法:

        zone_managed_pages / sysctl_lowmem_reserve_ratio[zone_index],这里Zone_managed_pages表示每个Zone的总内存,而sysctl_lowmem_reserve_ratio如下:
        

 

  • high wmark

         表示高水位内存。linux内存的回收机制受水位线控制,一般分为最小水位线(min wmark), 低水位线(low wmark)和高水位线(high wmark)。比如通过cat /proc/zoneinfo,我们可以看到如下关键信息:

  pages free    80916
        min      3072
        low      10533
        high    17994
        spanned  524288
        present  524288
        managed  466359 
        这里看到的high就是对应高水位线,对应17994个pages。
  • free left

        每个Zone的Free 内存扣除掉上述high wmark和lowmem reserve之后的值。

        Available-part1计算规则:
        1)求出当前每个Zone的最大lowmem reserve,记max lowmem reserve
        2)每个Zone的free 内存扣除掉max lowmem reserve和high wmark
        3)将2)中剩余的free内存(等价于free left减去max lowmem reserve与lowmem reserve的差)相加
 
        接着,是PageCache部分。这里的PageCache是指Active(file)和Inactive(file)之和。这部分贡献给MemAvailble的有多少呢?
        通过图可以获知Available-part2的计算规则:
        1)比较当前系统设置的低水位线内存与1/2的PageCache,取最小者
        2)PageCache扣除1)中的最小者
        由此可知,PageCache贡献大于或者等于其50%的量。
 
        再者,看KReclaimable部分。该部分的Available-part3计算规则与PageCache的类似:
        1)比较当前系统设置的低水位内存与1/2的KReclaimable,取最小者
        2)KReclaimable扣除1)中的最小者
        同样,KReclaimable的贡献量大于或者等于其50%。
 
        最后,三个部分相加,即可得到MemAvailable=Available-part1 + Available-part2 + Availabel-part3。
 
        综上,我们至少可以得到如下结论:
  • MemAvailable包含了MemFree的部分,以及可回收内存的部分
  • MemFree是实际可直接分配使用的内存,但不是系统全部可用内存;
  • MemAvailable的值受水位线的影响,即调整水位线(即影响MemAvailable的值)。
        另外,结合水位控制,从策略上你可以看出,通过high wmark之上的Free内存以及1/2(以上)的可回收内存纳入MemAvailable,表现的是比较“保守”和“安全”的做法,倾向于“能够”和“可信”地分配给出来的内存量统计(通俗将就是在我力所能及范围,“砸锅卖铁”——回收内存,就会满足你的需求)。而MemFree纯粹表征当前的空闲页,可以直接给分配的内存。但是MemFree会因为落入不同的水位区间,会触发不同的内存回收方式(kswapd回收和直接回收)。该部分属于水位控制与内存回收范畴,不在此处展开。
这样,我们可以回答文章开始提及的第二个问题:如何评估系统内存的紧张程度?两个参数需要结合看。如果MemFree很低,那么如果MemAvailable还很高(如600M),说明可回收的内存很高(PageCache+KReclaimable)。但是因为MemFree已经很低,比如10K,说明此时系统还没有及时回收内存(可能水位线设置较低,没有触发内存回收),导致很多进程处“等待“内存分配的状态(进入内存缓慢分配路径),系统性能将收到影响。但是如果MemFree与MemAvailable都很低,说明系统的内存真的已经接近消耗殆尽的状态。
posted @ 2023-06-04 00:30  无剑问天  阅读(722)  评论(0编辑  收藏  举报