在分析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的构成来自三个部分(注意不是全部):
对应/proc/meminfo的MemFree,就是客观上对应的系统可以“直接”分配使用的内存。
对应/proc/meminfo的Active(file)+Inactive(file),该部分内存可以通过回收之后分配使用
对应/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。
每类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如下:
表示高水位内存。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。
每个Zone的Free 内存扣除掉上述high wmark和lowmem reserve之后的值。
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,取最小者
由此可知,PageCache贡献大于或者等于其50%的量。
再者,看KReclaimable部分。该部分的Available-part3计算规则与PageCache的类似:
1)比较当前系统设置的低水位内存与1/2的KReclaimable,取最小者
同样,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都很低,说明系统的内存真的已经接近消耗殆尽的状态。