水线
既然谈到了内存的回收再利用,那么就一定有这么一个标准:
什么时候开始回收,什么时候结束回收
在内核中这个标准就是 水线。
水线的含义
水线定义在每个zone上,如下简易示意图所示。
一共有三条水线:min, low, high。那这三条水线是什么含义呢?用一张图来解释应该比较清楚:
从这张图上我们可以看出:
当内存容量小于低位水线,则开始启动kswapd回收内存
当内存容量小于最小水线,则开启直接回收
当内存容量高于高位水线,则kswapd可以休息
概念上还是很清楚的。
水线的计算
水线的计算在函数setup_per_zone_wmarks()中完成。不仅启动时会计算,还会在某些参数调整时再次计算。
整个计算过程其实不难,让我用伪代码解释一下:
首先系统启动时会计算出整个系统内存保留的最小值: pages_min。这个计算在init_per_zone_wmark_min()完成。 最低水线的计算依赖于这个值。每个zone的最低水线 = (当前zone的lowmem * pages_min) / total lowmem。
这意味着系统上所有zone的最小水线之和 = pages_min 也就是整个系统想要最少预留的内存。
PS: 这个pages_min的当前值可以从/proc/sys/vm/min_free_kbytes查看,不过需要转换一下。
接着就是计算低位和高位水线了:
可以看到这三个水线之间的距离是相同的,而这个距离则是当前zone内存容量的一个比例。默认这个比例是0.1%。
PS: 这里的watermark_scale_factor也可以从/proc/sys/vm/watermark_scale_factor查看。
好了,是不是挺简单的了。
水位查看
了解了计算过程,我们也可以来看看当前系统中真实设置的值。这个信息可以在/proc/zoneinfo中查到。
其中managed的页有243597,那么默认情况0.1%就是243个page。从上面的数据看,正好符合这个公式。
然后我们看一下这个水位对一个zone究竟是什么比例。
可以看到,对一个1G的zone来讲,高水位也就10M,而每个水位之间间隔1M。 这么看,要唤醒kswapd,那是内存已经非常紧张的时候了。
水线的调整
水线是可以调整的,这样可以让系统保有更多的内存可以使用。方法就是通过上面提到的两个文件
/proc/sys/vm/min_free_kbytes
/proc/sys/vm/watermark_scale_factor
前者抬高低水位,后者加大水位之间的间隔。
具体的效果可以从/proc/zoneinfo文件里查看,这里就不做具体展示了。
lowmem_reserve
除了水线,还有一个概念控制着什么时候进行内存回收 -- lowmem_reserve。准确的来说应该是这是水线的组成部分。
在判断水线的函数__zone_watermark_ok()中,我们可以看到这么一个判断:
也就是空闲页需要大于 水线(min) + lowmem_reserve[]才能算是水线达标。那么我们就来看看这个lowmem_reserve是怎么计算的吧。
setup_per_zone_lowmem_reserve()是设置lowmem_reserve[]的函数,让我们用一张图来展示一下这个概念:
其中采用的缩写标示为:
mp[i]: managed pages of zone[i]
ra[i]: sysctl_lowmem_reserve_ratio[i]
lr[i]: lowmem_reserve[i]
这么看来 zone.lowmem_reserve[i]的含义是如果要在zone上分配 zone[i]的内存,而此时zone上的内存小于zone.lowmem_reserve[i] + watermark,那么这个分配将出发回收动作。.
Last updated