zswap 是一个内核功能,它为交换页提供了一个压缩的内存缓存。原本会交换到磁盘的页被压缩并存储到内存中的存储池中。一旦池已满或内存耗尽,最近最少使用的(LRU)页就会被解压缩并写入磁盘,就好像它没有被拦截一样。将页解压缩到交换缓存后,可以释放池中的压缩版本。
与 zram 相比的区别在于,zswap 与 swap 设备协同工作,而 zram 是内存中的交换设备,不需要后备交换设备。
开关 zswap
在稳定版(stable)的 linux包 官方内核中,zswap 会被默认启用。这可以通过稳定版内核配置中的 CONFIG_ZSWAP_DEFAULT_ON
标志进行验证。
要在运行时禁用 zswap,请执行下面的命令:
# echo 0 > /sys/module/zswap/parameters/enabled
要永久禁用 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:lz4 /sys/module/zswap/parameters/zpool:z3fold /sys/module/zswap/parameters/accept_threshold_percent:90
见 zswap 文档获取不同参数的描述。
显示初始配置的引导时加载消息可以通过以下方式检索:
# dmesg | grep zswap:
[ 0.317569] zswap: loaded using pool lz4/z3fold
设定参数
使用 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=z3fold
当通过引导参数更改压缩算法时,需要确保在引导期间尽早加载相应的压缩模块(参考 #压缩算法)。
最大池大小
存储池不是预先分配的,它可以增长到可用内存总量的一定百分比,默认情况下最多占内存总量的20%。一旦达到此阈值,就会将页从池中逐出到交换设备中。压缩池的最大大小由参数 max_pool_percent
控制。
压缩存储池分配器
zpool 参数控制压缩存储池的管理。
在 6.3 版本后的内核中,添加了 zsmalloc 分配器。它在低内存条件下表现良好,并且可以节省更多内存。
对于较旧的内核,可以使用 zbud 数据分配器,它将恰好两个压缩页面存储到一个中,这将压缩比限制为 2 或更低。
同样, z3fold 分配器允许每页最多 3 个压缩对象(与 zbud 的 1.7 相比,典型的压缩比平均约为 2.7)。该分配器以前被建议优于 zsmalloc,因为它具有更好的性能,但由于这一点不再成立且存在众多错误,自 6.13 起已被弃用并默认禁用(在 6.6.55 中回移植到 6.6 LTS),并计划移除。
默认情况下会创建一个类型为 zsmalloc 的 zpool。使用内核参数 zswap.zpool
可以在启动时选择其他分配器。数据分配器也可以在后期通过 sysfs 接口进行更改。
压缩算法
对于页的压缩,zswap 使用内核加密 API 提供的压缩器模块。默认情况下会使用 lz4 压缩算法,但也可以在启动时使用 zswap.compressor
更改压缩算法。其他选项包括 deflate, lz4hc, lzo, lzo-rle, 842 和 zstd。
使用 sysfs 在运行时更改压缩不会有问题,但在本例中,zswap 从 lz4 开始,并在稍后阶段切换到定义的算法。要立即使用另一种算法启动 zswap,必须通过内核引导参数进行设定,并且内核必须尽早加载相应的模块。这可以通过以下步骤来实现:
- 将与所选压缩器相关的模块添加到 mkinitcpio#模块(MODULES)数组中。
- 修改 mkinitcpio 配置后重新生成 ramdisk 环境:见 mkinitcpio#创建和启用镜像。
- 在内核参数中将
zswap.compressor
设定为你选择的算法。
在下次启动时,见 #当前参数来检查 zswap 现在是否使用了请求的压缩器。