khugepaged
内核 THP 后台折叠线程
mm_slot 扫描链表 · 严格 FIFO
hot1
持续访问
cold
MADV_FREE
hot2
持续访问
队列头部
冷
队列尾部
…
逐个 PMD 区间检查
512 × 4KB 基页
折叠
2MB
大页
TLB 记录 512 → 1
dTLB miss 显著下降
每个唤醒周期的扫描预算
4096 页 ≈ 16MB(默认)
预算耗尽 → 睡眠 10 秒
khugepaged_scan_sleep_millisecs
醒来后接着扫
队尾的热内存只能干等
一条链 = 所有被管的进程
只问能不能拼,
不问这块烫不烫
预算是「页数」,
不是「干活量」
bpftrace · 观测一轮完整扫描
桌面机 · 闲置启动 10 分钟 · x86_64
SCAN_SUCCEED
1
SCAN_EXCEED_SHARED_PTE
2
SCAN_PMD_MAPPED
142
SCAN_NO_PTE_TABLE
178
已是大页 / 根本没有页表 → 看一眼就退出
总扫描进度 progress
674 MB
总耗时(含睡眠)
419 s
674MB 的「进度」
只换来
1 次
真正折叠
先量一轮:
真干成了多少活
322 次全是白看
674MB 是记账值
不是真扫过的页数
419 秒本可以给热内存
改动前
已合并
无页表
已合并
无页表
hot2 热区
+512
+512
+512
+512
?
扫描指针
预算耗尽 → 睡 10 秒
队尾热内存
一直等
419 秒
改动后
已合并
无页表
已合并
无页表
hot2 热区
+1
+1
+1
+1
+N 真扫
预算省下来
一个周期就够
预算花在真活上
同一个区间:早退只看一眼 —— 旧代码记 512 页,新代码记 1 页。
每个区间都记 512 页
干没干活都一样
4 个早退就吃掉一半预算
几十个 10 秒周期
才扫完一整圈
- progress += HPAGE_PMD_NR;
不管真扫了多少,一律记满 512 页
+ progress += 1;
每扫一个 PTE 记 1;早退整段也只记 1
匿名路径 · 按实际触碰的 PTE 数记账
查找 PMD
早退:已合并 / 无页表
+1
PTE 循环:逐个 PTE
+1
文件路径 · 走 xarray 取页,不遍历 PTE 表
SCAN_PTE_MAPPED_HUGEPAGE
→ +1
其余结果(含成功的 SCAN_SUCCEED)
→ +512
预算算实之后
廉价早退几乎不占额度,
队尾的热内存不必再等几十个周期。
同样的 4096 页预算
覆盖更多真正有活可干的区间
应用进程
madvise(MADV_FREE)
「这块内存可以丢,别回写」
匿名页 · 清掉 swapbacked 标志
lazyfree:可丢弃
khugepaged 仍然合并
它只看「能不能折叠」
2MB 大页
THP
属性丢失
普通 vma 里
大页不再「可丢弃」
紧张时只能 swapout
用户的「可丢弃」承诺作废
而合并本身,还白烧了 CPU
两个决策点:PMD 扫描阶段 · 隔离阶段 —— 同一道判定
条件 1
后台
khugepaged?
否
合并 · 放行
madvise_collapse()
显式请求必须照办
是
条件 2
lazyfree
内存?
否
合并 · 放行
匿名 + 未设 swapbacked
才算可丢弃
是
条件 3
PTE
干净?
否
合并 · 放行
PTE 变脏
用户又写入了它
是
条件 4
vma 非
可丢弃?
否
合并 · 放行
VM_DROPPABLE
属性由 vma 保留
四关全过
跳过合并
可丢弃属性仍保留
不再白烧 CPU
整轮扫描效率 · 桌面空闲 10 分钟
总扫描进度
−93.3%
674 MB
45 MB
总耗时(含睡眠)
−95.2%
419 s
20 s
同样扫完一遍链表,省下 95.2% 的时间
队尾 hot2 进程 · x86_64
cycles per access
4.96
→
2.21
−55.4%
dTLB-load-misses
284.8M
→
69.6M
−75.6%
测量方式:hot1 → cold → hot2 各 128MB
cold 短暂访问后 MADV_FREE;hot2 排在队尾
qemu-system-x86_64 -enable-kvm
dTLB-load-misses
241.6M
→
3.2M
−98.7%
kernbench · 并行内核编译
user −1.02% · syst −2.12% · elsp −0.99%
编译是 CPU 密集,收益温和
真正受益的是访存敏感的工作负载
省下的都是空转,真活没少
TLB 越紧张,收益越夸张
① 预算算实
匿名 PMD 区间
旧
+512 页
新
+1 页
早退整段也只记 1
② 跳过无意义折叠
后台扫描
lazyfree
干净 PTE
普通 vma
四关全过
跳过折叠
不再白烧 CPU
③ 预算投给热内存
总耗时
419 s
20 s
−95.2%
dTLB miss
队尾 hot2
x86_64
−75.6%
qemu
−98.7%
把有限的扫描预算花在真正会持续访问的内存上
空格
播放/暂停
←
→
逐动作
R
重播
⚠
1x