vmalloc 大映射
向 buddy 申请高阶页
立即 split_page
得到连续 order-0 页
为什么要拆?
要访问底层 struct page
只能保留 order-0
页仍然物理连续
适合按块回收
回归的起点
a06157804399
vmalloc 更倾向高阶
紧密 vmalloc/vfree
性能明显回退
问题不在拆分本身
而在释放时
高阶块被拆成单页还回去
分配
高阶页从 buddy 来
split 成 order-0
页仍连续排列
旧 vfree
逐页 __free_page
全部进 order-0 pcp
高阶优势丢失
回收形态退化
紧密循环
每次重新要高阶
pcp 供不上高阶需求
vfree 越来越慢
test_vmalloc 回归
不是正确性问题
是回收形态退化
连续页被逐页打散
free_contig_range
其它连续释放路径
本质上同一件事
释放连续 order-0
旧实现
for (; nr_pages--; pfn++)
__free_page()
每页单独归还
每页进 order-0 pcp
和 vfree 一样
高阶块被打散
回收优势丢失
两处都慢
同一个病根
共性
连续 order-0
应该按批处理
方案
把连续 order-0 当作一批
不再逐页 free
切成尽量大的块
最大 2 的幂块
且自然对齐
受 buddy 最大 order 限制
不超过剩余页数
对齐越大越省
整块归还
pcp 或 buddy
高阶块留在 pcp
下次更易取
恢复回收优势
关键
页状态仍逐页处理
但块可以整体归还
__free_contig_range_common
遍历每个 PFN
pfn_to_page 逐个取页
跨 section 也能处理
逐页 prepare
put_page_testzero(非 frozen)
free_pages_prepare
失败页不归还
HWPoison / 坏页
同 section 连续页
free_prepared_contig_range
__ffs 求对齐 order
调 __free_frozen_pages
一块块归还
section 检查
memdesc_section
未启用时编译器优化掉
新接口 free_pages_bulk
页数组 + 页数
找出连续 PFN 段
调 __free_contig_range
vfree 改造
先更新 NR_VMALLOC
再批量释放页数组
不再逐页 __free_page
cond_resched 保留
对齐 order-3 块
回到 order-3 pcp
恢复回收优势
按文章数据超过 baseline
不是所有块都这么大
假设
page_array 按 PFN 升序
乱序仍正确,但可能退化
free_contig_range
其它调用者
直接复用新 helper
也按块归还
__free_contig_frozen_range (CMA)
is_frozen=true
跳过 put_page
仍逐页 prepare
最后批量归还
prepare 失败
HWPoison
坏页
刻意不归还
不能回到分配器
一个 helper
三条路径
vfree / contig / frozen
page_alloc_high_order_test
alloc 高阶 + split + free_contig_range
10 万次
arm64 服务器
执行时间
4,097,358 us
→ 729,831 us
约 5.6 倍
文章主指标
test_vmalloc
多数高并发大块场景 +9%~+49%
相对 v6.18
fix_align_alloc_test p:1 仍约 -14%
相对 mm-new 的 -50% 已缓解
结论
不是所有场景都赢
但回归大幅缓解,连续页回收更快
空格
播放/暂停
←
→
逐动作
R
重播
⚠
1x