当前位置:首页>Linux>Linux 7.2 合入 SLUB 三大性能优化:延迟 freelist、批量操作与编译器赋能的"分配令牌"

Linux 7.2 合入 SLUB 三大性能优化:延迟 freelist、批量操作与编译器赋能的"分配令牌"

  • 2026-09-08 14:05:16
Linux 7.2 合入 SLUB 三大性能优化:延迟 freelist、批量操作与编译器赋能的"分配令牌"

内存分配器的一次"外科手术式"升级


Linux 7.2 合并窗口日前合入了一组针对 SLUB 分配器的性能优化补丁,涵盖三项核心改进:延迟空闲链表构建、批量 partial slab 分离/重接,以及颇具前瞻性的 Allocation Tokens(分配令牌) 机制。

这三项优化分别来自 ZTE 工程师盛明虎、内核开发者郝力,以及 LLVM/clang 编译器社区的前沿探索。本文逐一拆解其原理、收益与适用场景。


一、延迟空闲链表构建:不做无用功

问题在哪?

SLUB 分配器在分配一个新 slab(即一整页内存)时,传统做法是立即初始化整个 freelist——把 slab 内所有空闲对象的指针串成一个链表。这个过程需要遍历每个对象并写入指针,本身就是一笔不小的开销。

但一个关键观察是:当你批量分配对象时,新 slab 中的大部分(甚至全部)对象很快就会被分配出去。先构建 freelist 再逐个拆走,等于先把积木搭好再一块块拆掉——中间步骤完全是浪费。

优化思路

盛明虎提交的 commit dc795d4c 实现了"延迟构建":只在真正需要时才构造 freelist 指针。如果一次性分配走 slab 中的所有对象,那 freelist 根本无需完整构建。

收益多大?

基准测试 slub_bulk_bench 的数据很亮眼:

配置
单对象耗时降幅
CONFIG_SLAB_FREELIST_RANDOM=n
42% ~ 70%
启用随机化
58% ~ 69%

当然,这是最佳场景下的数字。实际负载的收益取决于"到达新 slab 的频率"——如果你的应用频繁触发新 slab 分配,收益就越明显。

具体应用场景?

对于运行 KVM 虚拟化、数据库或高频内存分配场景的宿主机来说,这意味着一部分 slab 分配路径的延迟被直接砍半。虽然单次分配节省的是纳秒级开销,但积少成多,在微服务网关、CDN 边缘节点这类对 tail latency 敏感的场景中,这种"无感优化"恰恰是最安全的性能提升——你什么都不用改,内核帮你省掉了无用功。


二、批量 partial slab 分离/重接:减少链表锁操作

问题在哪?

SLUB 维护着多个 partial slab 链表(部分空闲的 slab),分配和释放时频繁涉及将 slab 从链表中取出或放回。每次操作都要拿锁、遍历、调整指针——单个操作的开销不大,但架不住次数多。

郝力的提交 commit 0fc52dee 将这个过程的粒度从"逐个操作"改为"批量处理":一次性从链表中取下多个 slab,或者一次性将多个 slab 重接到链表中。

收益

  • will-it-scale mmap 基准测试提升 2%~5%
  • 减少 list 锁竞争和 cache line  bouncing

工程思维

这个优化思路在内核中并不陌生——将多次小操作合并为一次大操作,摊销固定开销。KVM 的批量 MMU 更新、IO 层的 bio 合并、网络层的 TSO/GRO……都是同一哲学的不同体现。

批量,是操作系统工程师对抗延迟的通用武器。


三、Allocation Tokens:让编译器教分配器"认人"

这是三个优化中最具前瞻性的一个。

思路

当前 SLUB 的 kmalloc cache 是按**大小(size class)**划分的——8 字节、16 字节、32 字节……不同大小的对象进入不同的 slab。但问题是:同一大小 class 中混入了不同类型的对象,它们的分配/释放模式可能完全不同,互相干扰导致碎片化和缓存效率下降。

Allocation Tokens 的思路是:利用 LLVM Clang 22+ 的编译器插桩,在分配点嵌入类型标签(token),让分配器知道"这个分配来自什么类型的对象",从而更智能地划分 cache。

技术栈

  • 需要 Clang 22+ 的支持(目前 LLVM 的最新开发版本)
  • 内核编译时需要开启特定的编译选项
  • 分配器根据 token 将同类型的对象分配到同一 slab 中

意义

这代表一种趋势:编译器与内核的边界正在模糊化。传统上,内存分配器对"谁在分配"一无所知——它看到的只是一个 size 和一个 GFP flag。而 Allocation Tokens 让编译器的静态类型信息流到了运行时分配器层面,类似 THP(透明大页)让虚拟化层更智能的思路。

当然,这个特性还处于早期阶段,实际收益的 benchmark 数据尚未完全公开。但它打开了一扇门:当编译器可以"告诉"分配器更多上下文,分配策略就能从"通用最优"走向"场景最优"。


四、对 KVM/虚拟化场景的连锁影响

作为一个内存密集型子系统,KVM 虚拟化对 slab 分配器的变化较为敏感:

优化
对 KVM 的影响
延迟 freelist
VM 启动时大批量分配减少延迟抖动
批量 partial 操作
内存热迁移、大页拆分等场景微秒级收益
Allocation Tokens
长期看,虚拟机控制结构(如 VMCS、kvm_vcpu)可分配到更紧凑的 cache 中

VM 启动时,内核需要为 vCPU、VMCS 区域、内存映射等结构大量分配 slab 对象。这些路径正好是上述优化的覆盖范围。


五、写在最后

Linux 7.2 的这一波 SLUB 优化,三个补丁各有侧重:

  • 延迟 freelist
    ——“不做不需要做的事”(减法思维)
  • 批量操作
    ——“把多次小操作合并成一次”(合并思维)
  • Allocation Tokens
    ——“让更多信息流到决策点”(信息思维)

这三种优化哲学,放在任何一个系统里都适用。

最后值得一提的是,两个关键补丁分别来自 ZTE 的盛明虎和独立内核开发者郝力——中国开发者在 Linux 内存子系统的影响力正在持续增长。Allocation Tokens 虽然当前依赖 Clang 22+,暂时无法进入大多数生产环境,但它代表的方向值得每个内核关注者持续跟踪。


参考:Phoronix — “Linux 7.2 Slab Changes Include More Performance Optimizations” (2026-06-17)

最新文章

随机文章