Linux内存回收水位

基于内核源码v5.14

Linux中物理内存的每个zone都有其自己的zone_watermarks,如下图所示,主要有三个限值,分别为:MIN,LOW和HIGH。


zone_watermarks

一、min值的取值


min的取值

如图所示,是内核中关于min_free_kbytes的取值的函数代码,单位为k。

min_free_kbytes是系统的保留内存的数量(以KB为单位),或者称之为保留池大小,主要用于保证一些类似于原子内存分配请求不会因为内存不足而阻塞。

可以看出,其取值是当前可用内存的总和(KB)与16的乘积的开方,结果以K为单位。

比如,加入当前可用内存为4GB,那么就是4M*KB,

就是对4M*16做开方,即8K*KB,即8MB。

当然,算出来的值并不是最终值,其规定的最大值和最小值。如图所示,最小值为128K,最大值为256M。


后续,每个zone中有关于水位min的设置,则是根据上面求得的保留内存的大小进行按比例分配。


二、low和high的取值

low和high的取值则取决于min的值。


这里的计算包含一个叫做"watermark_scale_factor"的系数,其默认值为10,对应内存占比0.1%(10/10000),可通过"/proc/ sys/vm/watermark_scale_factor"设置,最大为1000。当它的值被设定为1000时,如图中所示的tmp参数即为内存大小的10%(1000/10000)。

这样low就是在min的基础上加一个tmp。

high是在min的基础上加一个tmp,即在min的基础上加两个tmp。

三、内存回收与水位

(以下内容来自参考链接)

在进行内存分配的时候,如果分配器(比如buddy allocator)发现当前空余内存的值低于"low"但高于"min",说明现在内存面临一定的压力,那么在此次内存分配完成后,kswapd将被唤醒,以执行内存回收操作。在这种情况下,内存分配虽然会触发内存回收,但不存在被内存回收所阻塞的问题,两者的执行关系是异步的(之前的kswapd实现是周期性触发)。

这里所说的"空余内存"其实是一个zone总的空余内存减去其lowmem_reserve的值。对于kswapd来说,要回收多少内存才算完成任务呢?只要把空余内存的大小恢复到"high"对应的watermark值就可以了,当然,这取决于当前空余内存和"high"值之间的差距,差距越大,需要回收的内存也就越多。"low"可以被认为是一个警戒水位线,而"high"则是一个安全的水位线。


如果内存分配器发现空余内存的值低于了"min",说明现在内存严重不足。这里要分两种情况来讨论,一种是默认的操作,此时分配器将同步等待内存回收完成,再进行内存分配,也就是direct reclaim。还有一种特殊情况,如果内存分配的请求是带了PF_MEMALLOC标志位的,并且现在空余内存的大小可以满足本次内存分配的需求,那么也将是先分配,再回收。

那谁有这样的权利,可以在内存严重短缺的时候,不等待回收而强行分配内存呢?其中的一个人物就是kswapd啦,因为kswapd本身就是负责回收内存的,它只需要占用一小部分内存支撑其正常运行(就像启动资金一样),就可以去回收更多的内存(赚更多的钱回来)。

虽然kswapd是在"low"到"min"的这段区间被唤醒加入调度队列的,但当它真正执行的时候,空余内存的值可能已经掉到"min"以下了。可见,"min"值存在的一个意义是保证像kswapd这样的特殊任务能够在需要的时候立刻获得所需内存。


在内存分配时,只有"low"与"min"之间之间的这段区域才是kswapd的活动空间,低于了"min"会触发direct reclaim,高于了"low"又不会唤醒kswapd。


参考链接:

1. Linux内存调节之zone watermark :https://zhuanlan.zhihu.com/p/73539328

你可能感兴趣的:(Linux内存回收水位)