Linux内存警戒线&内存回收

min_free_kbytes

/proc/sys/vm/min_free_kbytes

代表系统所保留空闲内存的最低限(Kbytes)。

min_free_kbytes = sqrt(lowmem_kbytes * 16) = 4 * sqrt(lowmem_kbytes)(注:lowmem_kbytes即可认为是系统内存大小)

另外,计算出来的值有最小最大限制,最小为128K,最大为64M,但是通过proc接口设置就没这个限制。(当前centos3.10中默认为66M)

截图.png

/* don't ever allow to reserve more than 5% of the lowmem */

lowmem代表设备的物理内存大小吗?这点不是很清楚

min_free_kbytes的主要用途是计算影响内存回收的三个参数 watermark[min/low/high]

watermark

每个内存管理区(zone)都有一个数组watermark,内核定义了三个watermark来表示当前系统色好难过与空闲内存。

1) watermark[high] > watermark [low] > watermark[min],各个zone各一套(以page为单位的)

2)在系统空闲内存低于 watermark[low]时,开始启动内核线程kswapd进行内存回收(每个zone一个),直到该zone的空闲内存数量达到watermark[high]后停止回收。如果上层申请内存的速度太快,导致空闲内存降至watermark[min]后,内核就会进行direct reclaim(直接回收),即直接在应用程序的进程上下文中进行回收,再用回收上来的空闲页满足内存申请,因此实际会阻塞应用程序,带来一定的响应延迟,而且可能会触发系统OOM。这是因为watermark[min]以下的内存属于系统的自留内存,用以满足特殊使用,所以不会给用户态的普通申请来用。

3)三个watermark的计算方法:

 watermark[min] = min_free_kbytes换算为page单位即可,假设为min_free_pages。(因为是每个zone各有一套watermark参数,实际计算效果是根据各个zone大小所占内存总大小的比例,而算出来的per zone min_free_pages)

 watermark[low] = watermark[min] * 5 / 4

 watermark[high] = watermark[min] * 3 / 2

回收的方式主要是两种:

后台内存回收(kswapd):在物理内存紧张的时候,会唤醒 kswapd 内核线程来回收内存,这个回收内存的过程异步的,不会阻塞进程的执行。

直接内存回收(direct reclaim):如果后台异步回收跟不上进程内存申请的速度,就会开始直接回收,这个回收内存的过程是同步的,会阻塞进程的执行。

如果直接内存回收后,空闲的物理内存仍然无法满足此次物理内存的申请,那么内核就会触发 OOM (Out of Memory)机制,根据算法选择一个占用物理内存较高的进程,然后将其杀死,释放内存资源,直到释放足够的内存。

验证&测试

消耗内存工具

int main(int argc, char *argv[])

{

long long i = 0;

int size = 0;

if (argc != 2) {

printf(" === argc must 2\n");

return 1;

}

size = strtoull(argv[1], NULL, 10);

if (size == 0) {

printf(" argv[1]=%s not good\n", argv[1]);

return 1;

}

printf("1\n");

char *buff = (char *) malloc(size * UNIT);

if (buff)

printf(" we malloced %d Mb\n", size);

buff[0] = 1;

printf("2\n");

for (i = 1; i < (size * UNIT); i++) {

if (i%1024 == 0)

buff[i] = buff[i-1]/8;

else

buff[i] = i/2;

}

pause();

}

环境准备

查看设备参数

截图.png

关闭drop_caches后台进行,防止后模一分钟周期清除cache

mv /b_iscsi/bin/RAM_arrange.sh /b_iscsi/bin/RAM_arrange.sh.bak

生成cache

cat /mnt/backupSystem/test.txt > /dev/null

截图.png

开始消耗内存测试,测试当pages free低于watermark[low]时,cache回收

使用工具消耗内存

./mallocMb 1024 &(消耗1G)

截图.png

当前pages free已几乎接近watermark[low],而cache还未回收,当前low以上可分配空间最大值为:41.1875

((16683 - 6102) + (14936 - 14973)) × 4 ÷ 1024 = 41.1875

因此,分配一个大于该值的空间则可使得free内存低于low,从而触发异步kswapd进程开始回收内存(cache)

继续消耗内存

空间立刻申请成功,且cache空间持续下降,而pages free持续增长,直至达到high后停止增长、cache停止下降。

截图.png

所以,当pages free低于low后开始内存回收的结论得到证实。

继续消耗内存使得cache空间得到全部释放后,当低于min后是否可以触发OOM。

截图.png

持续消耗内存发现其中一个操作出现明显卡顿,且前后pages free增长,因此怀疑消耗内存低于了min水平线。

查看messages日志得到证实:

截图.png

拓展

考虑将min_free_kbytes的值设置变大后会有什么影响?

在总内存4G的设备中设置min_free_kbytes为1G,如图:

截图.png

持续进行内存消耗后,发现pages free在还未达到low以后,设备出现了hang机,所有指令均无法执行

截图.png

正常情况下,系统应该是在free低于min后OOM杀死进程得到空间释放,为什么还有空余内存空间,反而无法得到内存呢?

这个问题经过几天的资料查询,依然未得到答案,怀疑的地方有两点:

min_free_kbytes过大导致,官方建议该值用用不要超过%5的lowmem,但并没有说明原因,需要进一步查看预研

截图.png

posted @ 2022-10-19 09:39  strongself  阅读(927)  评论(0)    收藏  举报