ZONE_DEVICE memmap:大区域初始化拖慢 bind/rebind
nd_pmem / dax_pmem
bind / rebind 延迟
memmap_init_zone_device()
逐 PFN 循环
每个 struct page
逐字段赋值
重复赋值
pgmap / zone / nid / flags 大多相同
真正随 PFN 变化的只有:
section 位、page->virtual
cache 代价
每写 1 个 cache 行 → write-allocate
把 memmap 冷数据拉进 cache
写 1 次、少复用 → 挤掉热数据
100GB namespace ≈ 上千万个 struct page,成本直接体现在 bind/rebind 延迟
旧路径:把整份 struct page 重写 N 遍
memmap 数组(N 个 struct page)
每个 page 都把相同字段重写一遍
pgmap · zone · nid · flags
每个 page 重复写同样的值
section 位 · page->virtual
真正随 PFN 变化
大部分字段写是冗余
cached store
普通写路径
write-allocate
把 memmap 冷数据拉进 cache
memmap 写 1 次、近期少读 → 挤掉热数据,cache 代价纯属浪费
用第 1 个真实 page 播种模板
page #0
真实 memmap 条目
不是栈上对象
慢路径初始化 → memcpy 进模板
既有 page 初始化 / pageblock
辅助函数只认真实条目
为什么从真实 page 取种:辅助函数期待真正的 memmap 条目,而非栈上对象
其余 page:刷新差异字段后整块复制
刷新差异字段
section 位、page->virtual
模板整块复制
1 次结构化 memcpy
原本散在许多字段上的赋值,收敛成 1 次结构化复制
compound tail page 用同一思路
第 1 个 tail page 取种 → 其余 tail 整块复制
同一套模板逻辑覆盖 compound tail
第二层:写 memmap 不该污染 cache
普通 cached 复制
写入经过数据 cache
write-allocate 拉入 memmap
替换
memcpy_nontemporal()
non-temporal store 直达内存
绕过 cache,不驱逐热数据
x86 后端:memcpy_flushcache() 内的 MOVNTI
memcpy_flushcache()
fixed-size fastpath 扩到
32/48/64/80/96 字节
内联 MOVNTI
让模板复制快路径生效
64/80/96 对应 struct page 尺寸
无专用后端:宏别名退化为 memcpy()
调用点尺寸仍可见,保留 FORTIFY 覆盖
无需额外 drain
同一 CPU 的初始化序列,不是发布写;设备可见交接由调用方排序
fast path 改为无条件启用
template 路径始终开启
每个可复用模板播种后即启用
page_ref_set tracepoint 移除
KASAN / KMSAN 2 道 opt-out 移除
只留一条主路径
不再为局部调试
分叉初始化逻辑
为什么可以删掉这些特例
初始化仍在分发 struct page 之前完成
KASAN 特殊处理应落在底层 helper,而非 ZONE_DEVICE 调用点
memory_type 与 hugetlb 几何交给编译器 enum switch 检查
base v7.3-rc1 对比加上本系列
指标
Before
After
改善
VM nd_pmem rebind 均时
221.07 ms
71.93 ms
-67.5%
VM dax_pmem rebind 均时
191.20 ms
87.37 ms
-54.3%
物理机 nd_pmem/fsdax rebind
205.90 ms
69.13 ms
-66.4%
物理机 dax_pmem/devdax rebind
225.43 ms
90.67 ms
-59.8%
物理机 test_hmm memremap 均时(每 64GB)
≈116.5 ms
≈46.7 ms
-59.9%
arm64 VM nd_pmem rebind 均时
27.93 ms
14.53 ms
-48.0%
arm64 VM dax_pmem rebind 均时
27.87 ms
16.27 ms
-41.6%
时间取自 memmap_init_zone_device() 的 pr_debug 输出;VM rebind 为 30 次平均
VM nd_pmem rebind 均时(ms)
base v7.3-rc1 → 加上本系列
base
221.07
+ 模板复制
155.00
+ memcpy_nontemporal()
150.40
+ x86 内联 MOVNTI
71.93
模板复制单独约 -29.9%(221.07 → 155.00 ms)
memcpy_nontemporal() 切换本身仅 155.00 → 150.40 ms
其余增益来自 x86 内联 MOVNTI(→ 71.93 ms)
arm64 没有 MOVNTI fast path:改善全部来自通用模板复制
无专用后端的架构同样受益
空格
播放/暂停
←
→
逐动作
R
重播
⚠
1x