zswap
zswap 是一种内核特性,为交换页面提供压缩的 RAM 缓存。通常会被交换到磁盘的页面,会被压缩并存储在 RAM 中的内存池中。一旦内存池已满或 RAM 已耗尽,最近最少使用 (LRU) 的页面将被解压缩并写入磁盘,就像它没有被拦截一样。在页面被解压缩到交换缓存后,内存池中的压缩版本可以被释放。
与 zram 的不同之处在于,zswap 与 交换 设备协同工作,而 zram 在其上创建的交换是在 RAM 中的交换设备,不需要后备交换设备。
切换 zswap
zswap 可以在运行时切换,方法是向 /sys/module/zswap/parameters/enabled
写入 1
(启用) 或 0
(禁用)。例如,要在运行时禁用它
# echo 0 > /sys/module/zswap/parameters/enabled
要永久启用 zswap,请将 zswap.enabled=1
添加到你的内核参数。要在默认启用 zswap 的内核上永久禁用它,请改为添加 zswap.enabled=0
。
自定义 zswap
当前参数
zswap 有几个可自定义的参数。可以使用以下命令显示实时设置
$ grep -r . /sys/module/zswap/parameters/
/sys/module/zswap/parameters/same_filled_pages_enabled:Y /sys/module/zswap/parameters/enabled:Y /sys/module/zswap/parameters/max_pool_percent:20 /sys/module/zswap/parameters/compressor:zstd /sys/module/zswap/parameters/non_same_filled_pages_enabled:Y /sys/module/zswap/parameters/zpool:zsmalloc /sys/module/zswap/parameters/exclusive_loads:N /sys/module/zswap/parameters/accept_threshold_percent:90
有关不同参数的描述,请参阅 zswap 文档。
有关 exclusive_loads
参数(目前不在 zswap 文档中)的更多信息,请参阅 linux 内核源代码中的此注释。
可以使用以下命令检索显示初始配置的启动时加载消息
# dmesg | grep zswap:
[ 0.317569] zswap: loaded using pool zstd/zsmalloc
设置参数
使用 sysfs
每个设置都可以在运行时通过 sysfs 接口更改。例如,要更改 compressor
参数
# echo lz4 > /sys/module/zswap/parameters/compressor
使用内核启动参数
要持久化参数更改,必须将相应的选项(例如 zswap.compressor=lz4
)添加到内核启动参数。因此,要永久设置以上所有设置,必须添加以下内核参数
zswap.enabled=1 zswap.compressor=lz4 zswap.max_pool_percent=20 zswap.zpool=zsmalloc
当通过启动参数更改压缩算法时,需要确保在启动早期加载相应的压缩模块(请参阅 #压缩算法)。
最大池大小
内存池不是预先分配的,它被允许增长到可用总内存的某个百分比限制,默认情况下最高可达总 RAM 的 20%。一旦达到此阈值,页面将从内存池中驱逐到交换设备。最大压缩池大小由参数 max_pool_percent
控制。
压缩内存池分配器
zpool 参数控制压缩内存池的管理。
在 6.3 以后的内核中,添加了 zsmalloc 分配器。据称它在低内存条件下工作良好,并且可以节省更多内存。
对于较旧的内核,可以使用 zbud 数据分配器,它将正好两个压缩页面存储为一个,这会将压缩率限制为 2 或更低。
类似地,z3fold 分配器允许每个页面最多 3 个压缩对象(典型压缩率平均约为 2.7,而 zbud 为 1.7)。此前,建议使用 z3fold 而不是 zsmalloc,因为它具有更好的性能,但由于情况已不再如此,并且存在许多错误,因此它已被弃用,并且自 6.13 起默认禁用(在 6.6.55 中反向移植到 6.6 LTS),并且计划移除。
默认情况下会创建类型为 zsmalloc 的 zpool。在启动时使用内核参数 zswap.zpool
选择另一个分配器。数据分配器也可以在稍后阶段通过 sysfs 接口更改。
压缩算法
对于页面压缩,zswap 使用内核加密 API 提供的压缩模块。在官方内核中,默认使用 zstd 压缩算法,但这可以在启动时使用 zswap.compressor=
更改。其他选项包括 deflate、lzo、842、lz4 和 lz4hc。
在运行时使用 sysfs 更改压缩算法没有问题,但是 zswap 在这种情况下会以 zstd 启动,并在稍后阶段切换到定义的算法。要立即使用另一种算法启动 zswap,必须通过内核启动参数设置,并且相应的模块必须由内核早期加载。可以通过以下步骤实现
- 将所选压缩器所需的模块添加到 mkinitcpio#MODULES 数组。
- 重新生成 initramfs.
- 使用
zswap.compressor=
内核参数 设置压缩算法。
在下次启动时,查看 #当前参数 以检查 zswap 现在是否使用了请求的压缩器。
禁用回写
zswap 具有每个 cgroup 选项来禁用回写(即防止写入磁盘)。
有关示例用例,请参阅 电源管理/挂起和休眠#禁用 zswap 回写以仅将交换空间用于休眠。
Zswap 统计信息
要查看 zswap 统计信息,您可以运行此命令
# grep -r . /sys/kernel/debug/zswap/
/sys/kernel/debug/zswap/same_filled_pages:26274 /sys/kernel/debug/zswap/stored_pages:159898 /sys/kernel/debug/zswap/pool_total_size:171565056 /sys/kernel/debug/zswap/written_back_pages:787323 /sys/kernel/debug/zswap/reject_compress_poor:0 /sys/kernel/debug/zswap/reject_compress_fail:15860 /sys/kernel/debug/zswap/reject_kmemcache_fail:0 /sys/kernel/debug/zswap/reject_alloc_fail:0 /sys/kernel/debug/zswap/reject_reclaim_fail:31 /sys/kernel/debug/zswap/pool_limit_hit:0