zswap

来自 ArchWiki

zswap 是一种内核特性,为交换页面提供压缩的 RAM 缓存。通常会被交换到磁盘的页面,会被压缩并存储在 RAM 中的内存池中。一旦内存池已满或 RAM 已耗尽,最近最少使用 (LRU) 的页面将被解压缩并写入磁盘,就像它没有被拦截一样。在页面被解压缩到交换缓存后,内存池中的压缩版本可以被释放。

zram 的不同之处在于,zswap交换 设备协同工作,而 zram 在其上创建的交换是在 RAM 中的交换设备,不需要后备交换设备。

切换 zswap

提示: linux-rtlinux-rt-lts 默认启用 zswap。可以使用 zgrep CONFIG_ZSWAP_DEFAULT_ON /proc/config.gz 验证。

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),并且计划移除

默认情况下会创建类型为 zsmalloczpool。在启动时使用内核参数 zswap.zpool 选择另一个分配器。数据分配器也可以在稍后阶段通过 sysfs 接口更改。

压缩算法

对于页面压缩,zswap 使用内核加密 API 提供的压缩模块。在官方内核中,默认使用 zstd 压缩算法,但这可以在启动时使用 zswap.compressor= 更改。其他选项包括 deflatelzo842lz4lz4hc

在运行时使用 sysfs 更改压缩算法没有问题,但是 zswap 在这种情况下会以 zstd 启动,并在稍后阶段切换到定义的算法。要立即使用另一种算法启动 zswap,必须通过内核启动参数设置,并且相应的模块必须由内核早期加载。可以通过以下步骤实现

  1. 将所选压缩器所需的模块添加到 mkinitcpio#MODULES 数组。
  2. 重新生成 initramfs.
  3. 使用 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

参见