swap 槽位按 64MB 区域分树
64MB 区域 0
一棵 xarray tree
64MB 区域 1
一棵 xarray tree
64MB 区域 2
一棵 xarray tree
swap 槽位与 zswap entry 的映射记录在 tree 里
一个区域内部
xarray tree
slot 0
entry
slot 1
entry
slot 2
entry
slot 3
entry
一个 range 可能
跨多棵 tree
释放 range 时逐槽调用
swap_range_free
批量释放槽位
zswap_invalidate()
每个槽位调用一次
调用次数 = range 内的槽位数
调用方手里
type + offset
打包成 swp_entry
接口按单槽设计
函数里再解开
type + offset
两个值本来就在调用方手里
zswap 从未启用时
zswap 从未启用
没有 entry 需要失效
每个槽位仍查 xa_empty
调用次数跟着槽位数走
整段 range 的纯开销
static branch 缺失
zswap_store 的回退路径
store 失败或禁用
须清掉偏移上的残留 entry
手写逐页查找
tree 查找 + erase
空 tree 也发起 erase
没有 xa_empty 守卫
同一套失效逻辑写了两遍
invalidate 接口 range 化
旧
zswap_invalidate(swp_entry)
新
zswap_invalidate(type, offset, nr_entries)
整个 range 一次调用
调用方直传 type 与 offset,逐槽循环收进函数内部
函数内部的逐槽处理
按槽重算所属 tree
一个 range 可跨多棵
空 tree 跳过
空 tree 不做 erase
xa_erase 并释放 entry
逐槽做真正的失效
未启用时整体跳过
旧
逐槽 xa_empty 检查
每个槽位都要进一次 xarray
新
zswap_never_enabled()
整个 range 塌缩成一次分支判断
store 回退路径复用同一实现
zswap_store() check_old
需要清掉旧 entry
调用 zswap_invalidate()
删掉手写逐页循环
继承两道守卫
never-enabled 与 xa_empty
收益来自少掉的逐槽路径
Before
After
调用次数
每个槽位一次
→
整个 range 一次
swp_entry
每个槽位打包/解包
→
不再打包
未启用时
每个槽位 xa_empty
→
一次 static branch
store 回退
手写逐页循环
→
复用 invalidate
削掉的是路径开销,不是压缩成本
作者未提供性能数据,以上为代码逻辑推断
空格
播放/暂停
←
→
逐动作
R
重播
⚠
1x