2MB THP 缺页
demand fault
folio_zero_user()
清零后才能映射
清零 512 个 4KB 页
2MB / 4KB = 512
清零是纯写:没有读依赖,顺序直接影响预取器
页内顺序还不够,页与页之间也要连续
AMD Genoa EPYC 9J13 · 64GB region · 2.56 GHz · boost=0
基线 2MB 清零带宽(populate)
11.79
GB/sec
每 4KB 约 323ns
内存延迟约 100ns
留给预取器的余量很小
页 0
页 1
页 2
页 3
页 4
页 5
页 6
页 7
1
2
3
5
7
8
6
4
process_huge_page(addr_hint, nr_pages, ...)
n = (addr_hint - addr) / PAGE_SIZE; /* base = 2, l = 3 */
for (i = 0; i < l; i++) {
left_idx = base + i;
right_idx = base + 2*l - 1 - i;
clear_subpage(left_idx);
clear_subpage(right_idx);
}
半随机在哪
先清外周
再左右交替向缺页汇聚
缺页页最后清
页内顺序,页间跳跃
清 4KB 页
323ns
内存延迟
~100ns
323ns − 100ns = 223ns 的空档
预取器本有机会把下一页带进来
LLC cache-miss 率
10.96%
每 100 次 cache ref 约 11 次 miss
预取器只看到零散 4KB 写
页间跳跃 → 无法跨页预取
带宽被单页限制
process_huge_page()
半随机
clear_contig_highpages()
按地址顺序
1
2
3
4
5
6
7
8
clear_contig_highpages(page, addr, nr_pages)
{
for (i = 0; i < nr_pages; i++) {
cond_resched();
clear_user_highpage(page + i,
addr + i * PAGE_SIZE);
}
}
顺序化的收益
2MB(demand):11.76 → 23.58
+100.51%
1GB 原本就顺序清
→ 带宽基本持平
clear_user_highpages()
按范围清零
clear_user_pages() / clear_pages()
架构可覆盖 clear_pages()
clear_page() / arch override
x86:rep stos
系列的铺路
treewide:generic clear_user_page()
x86:clear_page_* 内联
去掉 CALL/RET(RETHUNK 下也不免费)
highmem:clear_user_highpages()
无 arch 支持:回退单页循环
32MB 一批
SZ_32M >> PAGE_SHIFT
= 8192 个 4KB 页
足够大:CPU 可按 extent 优化
足够小:限制不可抢占延迟
/* clear_contig_highpages() */
const unsigned int unit =
preempt_model_preemptible() ?
nr_pages : PROCESS_PAGES_NON_PREEMPT_BATCH;
for (i = 0; i < nr_pages; i += count) {
cond_resched();
count = min(unit, nr_pages - i);
clear_user_highpages(page + i,
addr + i * PAGE_SIZE,
count);
}
unit 取多大
可抢占 → nr_pages
不可抢占 + clear_pages → 32MB
无 clear_pages → 1 页(不可抢占时)
为什么是 32MB
≈ LLC 大小
10GB/s 下约 3ms
低于调度告警阈值
CPU 可按 extent 优化
x86 clear_pages():REP STOS / unrolled 处理整个 extent
extent > LLC:AMD Zen 省略 cacheline 分配
清零带宽(GB/s,demand)
2MB 前
11.76
2MB 后
23.58
1GB 前
24.85
1GB 后
25.40
LLC cache-miss 率
10.96%
→
0.73%
−93.3%
每 100 次 cache ref 约 11 次 → 不到 1 次
L2 预取器
+22%
预取的 cacheline
顺序让预取器跨页工作
顺序化后:2MB 翻倍;1GB 持平(本就顺序清)
① 顺序
clear_contig_highpages()
页与页连续,预取器可跨页
② 批量
clear_user_highpages()
一次交给硬件更大的 extent
先让访问连续,再把范围交给硬件
顺序解决可预测性;批量解决 extent 大小
2MB 带宽
11.76 → 23.58 GB/s
+100.51%
cache-miss 率
10.96% → 0.73%
−93.3%
1GB 带宽
24.85 → 25.40 GB/s
本就顺序清 → 持平
空格
播放/暂停
←
→
逐动作
R
重播
⚠
1x