定义了 SLUB 的统计计数器集合,每个值对应一个struct kmem_cache上的计数字段。它把 SLUB 内部所有关键的分配/释放/搬运动作分类计数,暴露到 sysfs/debugfs 供性能分析和调优。
一、整体作用
SLUB 在kmem_cache里有一个数组:
unsigned long stat[NR_SLUB_STAT_ITEMS]; // 或 per-CPU 版本
每次发生某类事件就s->stat[ALLOC_FASTPATH]++等。通过/sys/kernel/slab/<cache>/alloc_calls、free_calls、或CONFIG_SLUB_STATS下的/sys/kernel/slab/<cache>/属性,可以看到这些计数。
用途:
判断分配/释放走的是快路还是慢路
判断 partial 列表、CPU partial、页面分配器的压力分布
定位性能瓶颈(如慢路过多、CPU partial 频繁 drain)
评估调试标志对性能的影响
下面按语义分组。
二、分配路径计数
| 枚举 | 含义 |
|---|---|
ALLOC_FASTPATH | 从当前 CPU slab 的 freelist直接拿到对象——最快的无锁路径 |
ALLOC_SLOWPATH | 需要获取新的 CPU slab 才能分配——进入慢路径 |
ALLOC_FROM_PARTIAL | CPU slab 是从per-node partial 列表取得的 |
ALLOC_SLAB | CPU slab 是直接向伙伴系统申请新页得到的 |
ALLOC_REFILL | 从当前 slab 页的 freelist补充 CPU freelist(同一页内部补充) |
ALLOC_NODE_MISMATCH | 分配的 slab 节点与请求节点不匹配,需要切换 CPU slab |
这一组完整刻画了一次分配对象的来源:
ALLOC_FASTPATH → 最快,CPU freelist 有货 ALLOC_REFILL → CPU freelist 空,但从当前页还能补 ALLOC_FROM_PARTIAL → 当前页也空了,从 node partial 拿 ALLOC_SLAB → partial 也没有,向伙伴系统要新页 ALLOC_NODE_MISMATCH → 拿到/需要的页节点不符,换 CPU slab ALLOC_SLOWPATH → 上述非 fastpath 的总入口
ALLOC_FASTPATH比例越高,SLUB 越高效。
三、释放路径计数
| 枚举 | 含义 |
|---|---|
FREE_FASTPATH | 释放到当前 CPU slab——无锁快路径 |
FREE_SLOWPATH | 释放到非当前 CPU slab——需要加锁的慢路径 |
FREE_FROZEN | 释放到frozen slab(被某 CPU 冻结、不在 partial 列表上的页) |
FREE_ADD_PARTIAL | 该次释放使 slab被加入 partial 列表 |
FREE_REMOVE_PARTIAL | 该次释放是最后一个对象,slab 从 partial 移除 |
FREE_SLAB | slab整页归还给伙伴系统 |
关键点:
FREE_FASTPATHvsFREE_SLOWPATH:区分对象是否属于当前 CPU 正在用的 slab。前者无锁,后者要动 per-node 锁,性能差距明显。FREE_FROZEN:frozen 是 SLUB 的中间状态——一个 slab 被某 CPU 独占、从 partial 列表摘下但还没成为“当前 CPU slab”。释放到 frozen slab 说明跨 CPU 释放或 deactivate 过程中的情况。FREE_ADD_PARTIAL/FREE_REMOVE_PARTIAL/FREE_SLAB:刻画释放导致 slab状态迁移,最终可能整页回收。
四、CPU slab 停用(deactivate)相关
当一个 CPU 不再使用某个 slab(比如切换 CPU slab、CPU 下线、cache 销毁)时,要把这个 slab “停用”并放回 partial 列表或释放。这一组计数描述停用时 slab 的状态和去向:
| 枚举 | 含义 |
|---|---|
CPUSLAB_FLUSH | 放弃当前 CPU slab(主动 flush,如切换时) |
DEACTIVATE_FULL | 停用时该 slab 是满的(无空闲对象) |
DEACTIVATE_EMPTY | 停用时该 slab 是空的(全部空闲) |
DEACTIVATE_TO_HEAD | slab 被放到 partial 列表头部 |
DEACTIVATE_TO_TAIL | slab 被放到 partial 列表尾部 |
DEACTIVATE_REMOTE_FREES | 该 slab 含其他 CPU 远程释放的对象 |
DEACTIVATE_BYPASS | 隐式停用(bypass,绕过常规 deactivate 流程) |
用途:
DEACTIVATE_FULL多:说明 CPU slab 常被填满后才换,局部性好。DEACTIVATE_EMPTY多:说明 slab 常被用空,可能分配/释放模式分散。TO_HEADvsTO_TAIL:SLUB 按 slab 空闲程度决定放头还是放尾,计数反映策略命中情况。REMOTE_FREES:跨 CPU 释放频繁时,局部性差,性能可能受影响。BYPASS:隐式路径,通常出现在特殊场景。
五、CPU partial 相关
前面提过CONFIG_SLUB_CPU_PARTIAL:每个 CPU 除了当前 slab,还缓存一批 partial slab。这一组计数描述 CPU partial 的流入流出:
| 枚举 | 含义 |
|---|---|
CPU_PARTIAL_ALLOC | 分配时使用了 CPU partial(从 CPU partial 取到 slab) |
CPU_PARTIAL_FREE | 释放时补充了 CPU partial(把 slab 挂到 CPU partial) |
CPU_PARTIAL_NODE | 从node partial 列表补充 CPU partial |
CPU_PARTIAL_DRAIN | 把CPU partial 排空回 node partial(如超限时) |
用途:
CPU_PARTIAL_ALLOC高:CPU partial 命中好,减少了 node 锁竞争。CPU_PARTIAL_NODE高:本地 partial 不够,频繁向 node 要。CPU_PARTIAL_DRAIN高:CPU partial 经常超限被排空,说明缓存策略可能需要调cpu_partial。
六、cmpxchg 失败计数
| 枚举 | 含义 |
|---|---|
CMPXCHG_DOUBLE_CPU_FAIL | this_cpu_cmpxchg_double失败次数 |
CMPXCHG_DOUBLE_FAIL | slab freelist 更新时cmpxchg失败次数 |
这两个衡量无锁路径的竞争程度:
cmpxchg是无锁 CAS,失败意味着有并发修改,需要重试。CMPXCHG_DOUBLE_CPU_FAIL:针对 per-CPU 的 double cmpxchg(更新 freelist + 计数器)。CMPXCHG_DOUBLE_FAIL:针对 slab freelist 更新的 cmpxchg。
失败率高说明并发冲突多,可能影响性能,也可能促使 SLUB 回退到加锁路径。
七、order 回退
| 枚举 | 含义 |
|---|---|
ORDER_FALLBACK | order 回退发生次数 |
calculate_order()会优先选一个“对象数合适、order 尽量小”的方案。若理想 order 分配失败(内存碎片、水位不足),SLUB 会回退到更大的 order或不同的对象数方案。这个计数反映内存压力或碎片导致的分配妥协。
八、NR_SLUB_STAT_ITEMS
NR_SLUB_STAT_ITEMS
数组大小哨兵,必须放在最后。用于:
定义
stat[NR_SLUB_STAT_ITEMS]数组遍历输出所有计数
保证编译期维度正确
九、分组总结图
分配: ALLOC_FASTPATH ──► ALLOC_REFILL ──► ALLOC_FROM_PARTIAL ──► ALLOC_SLAB └─ ALLOC_NODE_MISMATCH ALLOC_SLOWPATH = 后几者总和 释放: FREE_FASTPATH / FREE_SLOWPATH / FREE_FROZEN └─ FREE_ADD_PARTIAL / FREE_REMOVE_PARTIAL / FREE_SLAB CPU slab 停用: CPUSLAB_FLUSH DEACTIVATE_FULL / EMPTY / TO_HEAD / TO_TAIL / REMOTE_FREES / BYPASS CPU partial: CPU_PARTIAL_ALLOC / FREE / NODE / DRAIN 无锁竞争: CMPXCHG_DOUBLE_CPU_FAIL / CMPXCHG_DOUBLE_FAIL 分配妥协: ORDER_FALLBACK
十、一句话总结
enum stat_item是 SLUB 的内部事件计数器清单:覆盖分配来源(fastpath/refill/partial/new page)、释放去向(fastpath/slowpath/frozen/partial/slab)、CPU slab 停用状态、CPU partial 流转、cmpxchg 竞争失败和 order 回退。它们通过/sys/kernel/slab/暴露,是分析 SLUB 行为和性能的核心依据。