出发点:简化
0ff67f990bd4
移除 swap slot cache
hibernation
跟随慢分配
部分设备
休眠耗时回归
用户报告
数百秒
回归不是所有设备都明显
但报告中的休眠耗时达到数百秒
数百秒是用户可感知的退化
为什么 hibernation 受影响更大
一次性分配大量连续 swap slot
慢分配频繁轮换 cluster,分配与写入都变慢
简化去掉了缓存,却没给 hibernation 留一条快路径
旧:每个 slot 都走慢分配
swap_alloc_hibernation_slot()
-> cluster_alloc_swap_entry(si, NULL)
没有复用当前 CPU 的 cluster
慢分配在做什么
扫描 free / nonfull / frag cluster
选中后锁定 cluster
从 cluster 里找一个可用 slot
每次都要重新选择和定位
代价
每次都可能换 cluster
cluster 频繁轮换
写入位置更随机
分配和写回都不在顺路径上
普通 swap 能接受这种开销
hibernation 是批量分配,放大了每次轮换的成本
所以问题在“没有快路径”,不是慢路径本身写错
hibernation 的访问模式
镜像按页写出
一路申请大量 slot
希望 slot 地址连续,写入也连续
旧路径的累积效应
分配一个 slot
走慢分配
选 / 换 cluster
旋转定位
写下一页
位置可能跳变
三个动作在大量 slot 上重复,成本不是一次性的
结果
分配变慢
写入分布更随机
部分设备休眠耗时到数百秒
新:先试 per-CPU 缓存的 cluster
swap_alloc_hibernation_slot()
-> 取本地 cluster 缓存
-> 失败才回退慢分配
命中条件
pcp_si == si
pcp_offset 有效
cluster_is_usable(ci, 0)
从 pcp_offset 继续扫描
回退
没有缓存 / 设备不匹配
cluster 不可用或已满
cluster_alloc_swap_entry()
和旧路径一样安全
只改 hibernation 分配入口
普通 swap 路径不变
快分配并不复杂,只是之前为简化没做
一次 hibernation slot 分配
取 per-CPU 缓存
si / offset
同一设备且 offset 有效?
cluster 可用?
复用 cluster
从上次 offset 继续
慢分配
重新选 cluster
命中时跳过选簇,失败则回退慢分配
代码路径(节选)
if (pcp_si == si && pcp_offset) {
ci = swap_cluster_lock(si, pcp_offset);
if (cluster_is_usable(ci, 0))
offset = alloc_swap_scan_cluster(...);
else
swap_cluster_unlock(ci);
}
if (!offset)
offset = cluster_alloc_swap_entry(si, NULL);
命中后更新 per-CPU offset,下一个 slot 继续
快路径的写入形态
同一 cluster 内继续分配
offset 向前推进
slot 留在同一 cluster
写回更接近顺序
写入开销下降
不再频繁跳转
旧路径
每个 slot 重新选 cluster
地址可能跳变
写入更随机
批量时不断累积
新路径
缓存 cluster 命中
从上次 offset 继续
分配与写入都更顺
一次选择,连续使用
不是改变 swap 格式
只是让休眠分配走一条更合适的路径
写入连续性是分配顺序带来的副产品
测试条件
Samsung SSD 830 Series
SATA II 3.0 Gbps · 6.19 基线
hibernation 耗时
324 秒
6.19 基线
35 秒
应用本系列后
~9x
约 9 倍
适用范围
作者原话:performance is several times better
单机、单设备数据,不外推所有 workload
快路径的边界
per-CPU cluster 缓存
不匹配、不可用或满时回退慢路径
只服务 hibernation
普通 swap 分配不受影响
一句话总结
批量休眠分配复用当前 cluster
不再每个 slot 轮换
分配更快,写入更连续
快路径简单,但收益在批量场景被放大
不要过度解读
9 倍来自这台 SATA II SSD
不是普遍吞吐承诺
空格
播放/暂停
←
→
逐动作
R
重播
⚠
1x