page fault 的匿名页重用路径上有大量冗余的 lru_add_drain()
页在 per-CPU pagevec
lru_add_drain()
刷到 LRU、refcount 降
判断是否独占
drain 的目的就是让 refcount 降下来 —— 但前提是 folio 真的在 pagevec 里
很多时候 drain 根本不会改变 refcount
沿用了很久的无条件 drain,如今开始露出浪费
两个失效点,成因不同
① drain 能降 refcount 才有用
folio 不在 lru_cache、
也不在 swapcache 里时
drain 不会改变 refcount,纯属浪费
② do_swap_page 的 drain 已冗余
swapcache 统一之后
refcount==1 检查不可达
无条件 drain 也失去意义
内存压力下 page fault 高频,冗余 drain 会叠加成可观开销
两个失效点,两套修法
一个改成按需,一个整段删掉
成因:swap table phase II 把 SYNC I/O swapin 也统一进 swapcache
SYNC I/O swapin
原先不走 swapcache
ASYNC I/O swapin
本来就走 swapcache
统一路径:SYNC 也进 swapcache
swap-in folio 至少有 base + swapcache 2 个引用
refcount==1 不再出现,那个检查成了死代码
这是第 2 类冗余的直接成因
修法一 · wp_can_reuse_anon_folio:按需 drain
folio_ref_count > 1 + in_lru_cache + in_swapcache
in_lru_cache
in_swapcache
drain 真能降 refcount 时才 drain
在函数顶部先记录这两个状态,拿它们修正 refcount 的下限
drain 从无条件变成有条件的
状态不满足就直接跳过,省掉一次刷洗
修法二 · do_swap_page:整段删除
删掉
stale refcount==1 检查
无条件 lru_add_drain()
改用
should_try_to_free_swap
FAULT_FLAG_WRITE 加 exclusive hint
直接决定要不要释放 swapcache
commit 4b34f1d8 之后 do_wp_page 已处理 non-exclusive,不必再用 refcount 推断
删除、删除、再换一个判断
swapcache 的释放判断也随之简化
收益:lru_add_drain 调用次数
zRAM swap + 20 线程 kernel build in memcg;行为计数,不是 wall/sys time
同一量程:满格 = 778,950 次,两组 bar 可直接比长短
1 GB memcg 限制
Before 276,278
After 226,318
减少
-18%
800 MB memcg 限制
Before 778,950
After 541,149
-30.5%
内存压力越大,冗余 drain 被消掉的比例越高
800 MB 限制下 -30.5%,1 GB 限制下 -18%
另外两处观测
5000+
Ubuntu boot 观察到的冗余 local LRU drain
43000+
1G memcg minimal kernel build 跳过的 drain
作者只以 drain 计数为准
未提供 wall time / sys time 数据
空格
播放/暂停
←
→
逐动作
R
重播
⚠
1x