swap 预读有两条路径
按聚簇预读
按 VMA 预读
两条路径都在预读循环结尾无条件刷一次 LRU
把刚加进 swap cache 的预读页推上 LRU
这行代码是 2.6.12 时代留下来的,本意是让预读页立刻上 LRU
本意是让预读页立刻上 LRU
但今天的调用方,还要求预读页此刻住在 LRU 上吗?
逐一读调用方:没有谁需要预读页此刻住在 LRU 上
换入缺页处理
连目标页之外的预读页
都不看一眼
shmem 聚簇换入
消费的是点名要换入的
那一页目标 folio
swapoff 全量换回
同样不依赖预读页
驻在 LRU
拿到目标 folio 后直接加锁、等写回完成、再操作 —— 全程不查它在不在 LRU
预读页在不在 LRU,对每个调用方都不影响结果
shmem 聚簇换入与 swapoff 全量换回都是如此
代价:把没填满的批次同步刷掉,还多抢一次锁
预读页加进 swap cache
per-CPU 批次
还没填满
结尾同步刷洗
多抢一次 LRU 锁
176 CPU 生产机:每分钟约 2.8 万次(28K)
在内存压力负载下,这条路径每分钟把批次中的 folio 搬上 LRU
刷掉的其实是没填满的批次,锁却每轮都要抢一次
这是很可观的 LRU 锁流量来源
唯一需要 folio 驻在 LRU 的,是写缺页路径
写缺页
为让目标页准确计引用
需要驻在 LRU
该路径自行刷洗
那个站点正是 #30 那条线改的,所以不需要预读在结尾代劳
要么不依赖 LRU,要么自己刷洗
结尾这趟无条件刷洗,对所有人都是空操作
方案:删掉两条预读路径结尾的这两处刷洗
直接延续 commit 1aa43598c03b:同类刷洗此前已从释放 swap cache 的路径上移除
旧 · readahead 结尾无条件刷洗
结尾无条件刷上 LRU
未满批次被同步刷掉
每轮多抢一次 LRU 锁
新 · 交给 per-CPU 批次自然排走
预读页留在 per-CPU 批次里
批次填满时自然排走
或下次回收与压缩时全量刷洗带走
没有新增机制:只是删掉两处多余的同步刷洗
预读页仍会随批次填满或下一次回收自然上 LRU
作者未提供吞吐 benchmark
给的是行为观测数据:176 CPU 机上每分钟约 2.8 万次,其余从机制推断
① 消除未满批次的同步 flush
原本每轮预读都要把没满的批次刷掉
② 去掉每轮一次的 LRU 锁竞争
预读结尾不再强制去抢那把锁
③ 预读页仍走 per-CPU 批次
行为不变:批次填满或下次回收自然排走
与 #30 同族:都在删冗余刷洗,但路径不同、作者不同
同承 1aa43598c03b 那次前体清理,落点却是另一条代码路径
空格
播放/暂停
←
→
逐动作
R
重播
⚠
1x