动机
我在这里写了一个答案:我的系统上的“水印”内存预留有多大? “正常”区域的“最小”水印显示为 31449 页。这是 125796 KiB - 比我的整个min_free_kbytes
(67584) 大。
重置将此区域min_free_kbytes
的水印设置min
为预期级别(例如 9582 页)。但过了一段时间,它又回到了更高的水平。
我相信这是由于boost_watermark()。它将“min”、“low”和“high”水印提升相同的数量。 watermark_boost_factor是 15000,所以最大提升应该是原始“高”水印的 150%...
问题
为什么我的“高”水印一开始就这么高?(以及“低”水印):
由于我的watermark_scale_factor是 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
我弄清楚了为什么水印之间的距离与 0.1% 的数字不匹配。
在“小型系统”上,水印之间的距离是(未增强的)“最小”水印的四分之一。即
managed * watermark_scale_factor / 10000
,如果记录的距离小于min / 4
(对于给定区域),则不使用记录的距离。tmp >> 2
相当于tmp / 4
。源码链接:linux-5.0.17/mm/page_alloc.c:7531
我还注意到这里最近有一个错误。“high-low”和“low-min”之间不应该有区别!这可能会发生,因为
min_wmark_pages(zone)
取决于zone->watermark_boost
已设置,但在此之前调用它。我已经向维护人员报告了这个错误。