背景

SLUB 用 percpu sheaves 替换了旧的 cpu partial slabs,给每颗 CPU 一个快速的对象缓存。sheaves 在某颗 CPU 上有效工作,前提是这颗 CPU 所在的 NUMA 节点已分配了 barn,也就是对象缓存的「仓」。可旧的实现只为有内存(N_MEMORY)的节点分配 barn,因为那里才有节点级的缓存管理结构,仓指针原本就挂在它身上,目标是缓存节点本地对象。

┌──────────────────────────────────────┐
│ per-CPU sheaves 只在有内存的节点建仓 │
└──────────────────┬───────────────────┘
                   ▼
┌──────────────────────────────────────┐
│    无内存节点没有仓,sheaves 失效    │  分配退回慢路径,slub 统计大量慢路径
└──────────────────┬───────────────────┘
                   ▼
┌──────────────────────────────────────┐
│      多节点无内存的系统尤其严重      │  8 节点仅 2 节点有内存的系统回归
└──────────────────────────────────────┘

这套逻辑在「无内存节点」上断了。当一个 NUMA 节点 online 却没有物理内存时,它没有 barn,sheaves 在这个节点的 CPU 上就失效了,分配不得不退回慢路径。Ming Lei 报告的回归就是这么来的:一台 8 个 online NUMA 节点、却只有 2 个有内存的机器,slub 统计显示出大量慢路径分配。

问题

  • percpu sheaves 只在有内存节点建 barn
  • 无内存节点没有 barn,sheaves 失效
  • 分配退回慢路径,slub 统计可见大量慢路径
  • 多节点无内存的系统尤其严重

方案

核心思路是让无内存节点也用得上 sheaves:既要在那里建仓、缓存非本地对象(反正本地对象本就不存在),又要让对象的归还与释放都走得通快路径。

旧:只给有内存的节点建仓
┌────────────────────────────┐
│      无内存节点没有仓      │
└─────────────┬──────────────┘
              ▼
┌────────────────────────────┐
│ sheaves 失效,分配走慢路径 │
└────────────────────────────┘

新:所有在线节点都建仓
┌──────────────────────────────────┐
│ 无内存节点也有仓,缓存非本地对象 │
└────────────────┬─────────────────┘
                 ▼
┌──────────────────────────────────┐  归还按本 CPU 节点定位仓,不再借最近有内存
│   分配与释放都走 sheaf 快路径    │  节点
└──────────────────────────────────┘

让无内存节点也有仓

旧实现把仓指针挂在每个有内存节点才有的节点级结构体里,于是只有有内存节点建得了仓。先把这层耦合拆开,让每个在线节点都能独立持有仓;再用一个节点位图记录哪些节点建了仓,并在 CPU 热插拔回调里补建,因为无内存节点正是随 CPU 上线而进入在线状态的。

让对象归还到本节点的仓

仓建好还不够,对象得真的流进来。对象归还的落点原本取「最近有内存节点」,于是无内存节点上的 sheaves 永远收不到对象;改为取本 CPU 所在节点(它可能就是无内存节点),对象就归还到本节点的仓里,不再借最近有内存节点的仓。

让释放也走快路径

分配侧通了,释放侧还堵着。无内存节点上释放对象时,因为对象都是远端的,局部性判定一律不通过,只能走慢路径。可这些节点本就分配不到本地对象,与其一律走慢路径,不如放宽判定、允许远端对象进 sheaves。这条判定被抽成一个共用的内联函数,让归还与释放共用同一套规则。代价是分配侧从 sheaves 拿到的对象平均距离变大:原先释放一律走慢路径时,sheaves 靠 zonelist 顺序回填,能凑到距离更近的对象。

附带的好处:CONFIG_HAVE_MEMORYLESS_NODES=y 的系统上,之前无内存节点借最近有内存节点的 barn,随着无内存节点增多、barn 锁竞争上升;现在各节点有自己的 barn,竞争下降,代价是内存消耗略增。

收益

作者未提供量化 benchmark。从机制与回归动机推断的预期收益:

  • 无内存 NUMA 节点上的分配不再因 sheaves 失效而退回慢路径
  • 无内存节点上的释放也走 sheaf 快路径,不再总走慢路径
  • CONFIG_HAVE_MEMORYLESS_NODES=y 系统上 barn 锁竞争下降(各节点独立 barn)

作者说明回归动机:8 个 online NUMA 节点仅 2 个有内存的系统上,slub 统计显示大量慢路径分配。