动机
我在这里写了一个答案:我的系统上的“水印”内存预留有多大? “正常”区域的“最小”水印显示为 31449 页。这是 125796 KiB - 比我的整个min_free_kbytes
(67584) 还要大。
重置将此区域的水印min_free_kbytes
设置min
为预期级别(例如9582 页)。但过了一段时间,又回到了更高的水平。
我确信这是由于boost_watermark()。它增强了“最小”、“低”和“高”水印相同数量。 水印升压因子是15000,所以最大提升应该是原来“高”水印的150%......
问题
为什么我的“高”水印一开始就这么高? (还有“低”水印):
自从我的水印比例因子为 10,“min”、“low”和“high”之间的距离应该仅为区域大小的 0.1%。但如果我在重置后立即查看min_free_kbytes
,“min”和“low”之间的差异是区域大小的 2%。为什么?
(“低”和“高”之间的差异是区域大小的 0.2%。所以这也不是我们所期望的!)。
我认为设置水印的代码位于__setup_per_zone_wmarks()。
内核版本:5.0.17-200.fc29.x86_64
从/proc/zoneinfo
:
Node 0, zone Normal
pages free 74597
min 9582
low 34505
high 36900
spanned 1173504
present 1173504
managed 1140349
我在 DMA32 区域中没有看到如此巨大的差异。看起来“最小”水印在 DMA32 区域中也没有得到提升,可能是因为内核更喜欢从“正常”区域分配。
Node 0, zone DMA
...
pages free 3961
min 33
low 41
high 49
spanned 4095
present 3996
managed 3961
...
Node 0, zone DMA32
pages free 334671
min 7280
low 9100
high 10920
spanned 1044480
present 888973
managed 866356
答案1
我弄清楚了为什么水印之间的距离与 0.1% 的数字不匹配。
在“小型系统”上,水印之间的距离是(未增强的)“最小”水印的四分之一。即,如果记录的距离managed * watermark_scale_factor / 10000
小于min / 4
(对于给定区域),则不使用该距离。
} else {
/*
* If it's a lowmem zone, reserve a number of pages
* proportionate to the zone's size.
*/
zone->_watermark[WMARK_MIN] = tmp;
}
/*
* Set the kswapd watermarks distance according to the
* scale factor in proportion to available memory, but
* ensure a minimum size on small systems.
*/
tmp = max_t(u64, tmp >> 2,
mult_frac(zone_managed_pages(zone),
watermark_scale_factor, 10000));
zone->_watermark[WMARK_LOW] = min_wmark_pages(zone) + tmp;
zone->_watermark[WMARK_HIGH] = min_wmark_pages(zone) + tmp * 2;
zone->watermark_boost = 0;
tmp >> 2
相当于tmp / 4
.
源码链接:linux-5.0.17/mm/page_alloc.c:7531
我还注意到这里最近有一个错误。 “高-低”和“低-最小值”之间不应该有区别!这种情况可能会发生,因为min_wmark_pages(zone)
取决于zone->watermark_boost
是否已设置,但在发生之前会调用它。我有报道将错误交给维护人员。