mmap_miss
readahead 启发式输入
同步 mmap 预读时 ++
映射命中时 --
计数
++ 需要同步预读
-- page cache 命中
超过 MMAP_LOTSAMISS
判定随机访问
作用
停掉预读
避免无用 IO
计数要准
否则误判
背景
未命中多则停预读
命中多则继续
递减侧 · 两类误 credit
命中被高估
计数被压低
启发式误判顺序
fault-around
附近 PTE 一并装
都算命中
fault 只证明
faulting address
retry
同步预读返回 VM_FAULT_RETRY
retry 映射同一页
同一 miss 被抵消
多算一次命中
问题
两类过度 credit
两类都压低计数
Fault-around · 附近 PTE
缺页装上附近 PTE
fault 只访问一个地址
附近没有真的访问
旧计数
每映射一页
mmap_miss--
附近全算命中
计数虚低
后果
随机访问
也被当成顺序
继续预读
无用 IO
误 credit
附近 PTE 没被访问
不该算命中
Retry · 同一个 miss
fault 启动同步预读
释放 mmap_lock
返回 VM_FAULT_RETRY
第一次
readahead 带入页
miss 已经 ++
等待 IO
retry
retry
页已在 cache
直接 map
又算命中
同一 miss 被抵消
误 credit
重试不是新命中
同一 miss 不能抵两次
方案 · 两处收紧
fault-around:只算故障地址
retry:FAULT_FLAG_TRIED 不算
两处必须一起改
fault-around
helper 返回 map_ret
只认 NOPAGE
附近 PTE 不算
workingset 仍保留
retry
检查 FAULT_FLAG_TRIED
重试不减
同一 miss 不抵消
计数扳回
关键
单独改不彻底
组合才彻底
Ablation · 单独不彻底
20 GiB
pgpgin GiB
P1 fault-around / P2 retry
random
baseline 223.377 GiB
P1 223.268 GiB
P2 223.257 GiB
P1+P2 1.010 GiB
stride2053
baseline 409.584 GiB
P1 409.584 GiB
P2 15.722 GiB
P1+P2 0.970 GiB
关键
单独改不彻底
组合才到约 1 GiB
数据 · 20/4 GiB
20 GiB larger / 4 GiB fit
cold cache / 1% 访问
3 次中位数
20 GiB larger
random 223.377 → 1.010 GiB
random 101.293 → 4.790 s
stride2053 409.584 → 0.970
stride4099 406.452 → 0.975
4 GiB fit
random 3.987 → 0.980 GiB
stride2053 3.991 → 0.811
fit-in-memory
趋势一致
口径
pgpgin 是块输入近似
不是常驻内存
边界 · 不是万能
stride1021 仍 204 GiB
顺序 pgpgin 不变
只修计数
stride1021
ra_pages = 2048
窗口 ±1024
stride 4084 KiB
落回读窗口
结论
随机/大步长
降到约 1 GiB
不是所有模式
作者明确边界
边界
只针对计数误 credit
不外推所有稀疏访问
空格
播放/暂停
←
→
逐动作
R
重播
⚠
1x