slab 为每个对象维护一个 slabobj_ext
slab
每个对象一份扩展信息
每个对象一份
struct slabobj_ext
objcg → memcg 计账
codetag_ref → allocation profiling
按对象存放
数量与 slab 对象同阶
所以 ext 的大小是一笔不可忽视的每对象开销
占多大、含哪些字段,只由编译期 config 决定
CONFIG_MEMCG
objcg 字段
CONFIG_MEM_ALLOC_PROFILING
codetag_ref 字段
两个 config 都打开时
每个 slabobj_ext 同时带 objcg 与 codetag_ref
哪怕 profiling 没在 boot 时启用
哪怕这个 cache 根本不做 memcg 计账
字段闲置,内存照占
页分配器没有这个问题;受影响的是 slab 与 percpu
改动前:两个字段各占一份
objcg
codetag_ref
改动后:共用同一份空间
union
谁用谁占
字段按需占用
哪些字段真被用,才分配哪些
不再由 config 一开就全占
union 是整套修复的地基
剩下两件事:何时省 codetag_ref、何时省 objcg
情况一:profiling 配置开了,boot 时没启用
整个 codetag_ref 都不需要
由 slab_obj_ext_has_codetag() 判定
这种配置下直接不分配
slabobj_ext
codetag_ref
不分配
profiling 运行时是否启用,决定要不要这个字段
config 只表示能力,不代表这次启动真的在用
省的是整块 codetag_ref
不是缩小字段,而是这次根本不分配
情况二:有些 cache 根本不做 memcg 计账
profiling 启用时,对它们不分配 objcg
KMALLOC_NORMAL
不需要 objcg
KMALLOC_NO_OBJ_EXT
明确标记不需要
为什么普通 kmalloc 能确定不需要
带 __GFP_ACCOUNT 的 kmalloc 走 KMALLOC_CGROUP
(SLUB_TINY 除外)
其余 cache 能确定不需要 objcg
kfence 对象也不再保留 obj_ext
这一条与 cache 类型无关
棘手的是具名 kmem_cache
带 SLAB_ACCOUNT
一定需要 objcg
不带 SLAB_ACCOUNT
分配可能部分带 __GFP_ACCOUNT
事先无法判断
引入内部标志 SLAB_MAY_ACCOUNT
应用到所有 cache(kmem 计账禁用的除外)
只有 KMALLOC_NORMAL 与 KMALLOC_NO_OBJ_EXT 不加
KMALLOC_NORMAL 若别名 KMALLOC_RECLAIM 则例外
不确定的 cache 先按「可能需要」保留 objcg 能力
后续可把 SLAB_MAY_ACCOUNT 显式化
只对确知使用 __GFP_ACCOUNT 的 cache 生效
预期收益
省 codetag_ref
profiling 未启用时不再占
每对象都少一份闲置字段
省 objcg
不需要计账的 cache 不分配
KMALLOC_NORMAL 等直接省
整体降开销
每对象元数据按需占用
更适合通用发行版 config
回归检查
forward-port 自 slub_kunit 的微基准
3 种 profiling 场景下有噪声但无明显回归
没有量化节省数据
作者只给了机制推断;全启用场景可能差几个百分点
预计真实负载不可见
空格
播放/暂停
←
→
逐动作
R
重播
⚠
1x