zram

来自 Arch Linux 中文维基

zram,旧称为 compcache,是一个用于在内存中创建压缩的块设备的 Linux 内核模块,即带实时磁盘压缩的内存盘。通过 zram 创建的块设备可以用作 swap 或是内存盘。zram 有两个常见的应用场景,一个是储存临时文件(/tmp),另一个是用作 swap。早期 zram 只有前一个功能,也是它原名 “compcache” (compressed cache) 的由来。

作为 swap 的使用[编辑 | 编辑源代码]

在最开始,创建出的 zram 块设备并不会预留或使用任何内存。仅当有文件需要被或者想要被交换出内存时,它们才会被压缩并移入 zram 块设备。因此,zram 块设备将会根据需要动态地增长或收缩。

例如,考虑一个具备 32 GiB 内存的系统,其上配置了容量为 64 GiB 的 zram。假设 zstd 能够实现 1:4 的压缩比率,当被全部占用时,该 zram 块被压缩后在物理内存中占用的大小将在 16 GiB 左右。因此:

  • 当内存和 zram 均完全被占用时:16 GiB 内存 + 64 GiB zram (在内存中约占用 16 GiB)
  • 正常使用且未发生交换时:32 GiB 内存 + 0 GiB zram
  • 正常使用且发生少数交换时:30 GiB 内存 + 8 GiB zram (在内存中约占用 2 GiB)
  • 不进行任何 zram 配置:32 GiB 内存

可见,zram 总是提供能在内存中存储更多内容的优势。

注意:
  • 假如相关的 zswap 内核功能为启用状态,它将阻碍 zram 的有效使用。这是因为 zswap 会在 zram 之前被用作 swap 缓存,并在换出的内存分页到达 zram 前对其进行拦截和压缩。在这种情况下,大多数的 zram 其实并未被使用,尽管 zramctl(8) 的输出可能并非如此。
  • 如上所述,在配置 zram 时,zram 设备的大小控制着其能存储的最大未压缩数据量,而非最大压缩后数据量。您可将 zram 的大小配置为与您系统的物理内存容量相等,甚至更大,只需保证数据压缩后所占用的大小不超过系统物理内存的容量即可。
  • 不支持在休眠时将内存换出至 zram,即便 zram 被配置在位于永久性存储的设备上。logind 会阻止休眠到配置在 zram 上的交换空间的尝试。

手动应用[编辑 | 编辑源代码]

首先,通过 sysfs 禁用 zswap

# echo 0 > /sys/module/zswap/parameters/enabled

接着,配置一个采用 zstd 压缩、32GiB 容量且优先度较高的 zram 设备 (仅对当前会话生效):

# modprobe zram
# zramctl /dev/zram0 --algorithm zstd --size 32G
# mkswap -U clear /dev/zram0
# swapon --priority 100 /dev/zram0

如需禁用,可以重启或执行以下命令:

# swapoff /dev/zram0
# modprobe -r zram
# echo 1 > /sys/module/zswap/parameters/enabled

关于每一步操作、配置选项及潜在问题的详细信息可以参考 zram 模组的官方文档

若需一个持久化的解决方案,请在下属章节所述的方法中任选其一。

使用 udev 规则[编辑 | 编辑源代码]

以下的案例描述了如何通过单个 udev 规则自动在启动时配置 zram 内 swap。该案例无需额外的软件包。

在开始之前,通过内核参数或 sysctl knob 永久性 禁用 zswap

显式地 在启动时加载模组

/etc/modules-load.d/zram.conf
zram

创建如下的 udev 规则 (请按需调整 disksize 属性):

/etc/udev/rules.d/99-zram.rules
ACTION=="add", KERNEL=="zram0", ATTR{comp_algorithm}="zstd", ATTR{disksize}="4G", RUN="/usr/bin/mkswap -U clear /dev/%k", TAG+="systemd"

/dev/zram 以一个高于默认值的优先度添加到您的 fstab

/etc/fstab
/dev/zram0 none swap defaults,pri=100 0 0
注意: 不能在 fstab 中使用 LABEL 或 UUID 对 zram 上的交换空间进行引用,因为 udev 不会为 zram 设备创建 /dev/disk/by-label/*/dev/disk/by-uuid/* 的符号链接。

使用 zram-generator[编辑 | 编辑源代码]

zram-generator 提供一个 systemd-zram-setup@.service 单元,可自动初始化 zram 设备而无需用户启动/启用相关模板或实例。详见 zram-generator(8)zram-generator.conf(5)

在开始之前,通过内核参数或 sysctl knob 永久性 禁用 zswap[1]

接下来,要创建一个使用 zstd 压缩、大小为所有可用内存容量一半的 zram swap 设备,只需安装 zram-generator,然后创建包含如下内容的 /etc/systemd/zram-generator.conf 配置文件:

/etc/systemd/zram-generator.conf
[zram0]
zram-size = ram / 2
compression-algorithm = zstd
swap-priority = 100
fs-type = swap

执行 daemon-reload,然后启动您所配置的 systemd-zram-setup@zramN.service 等实例。

您可使用 zramctl(8) 命令,或是通过查阅 systemd-zram-setup@zramN.service 实例的单元状态,来检查您所配置的 /dev/zramN 设备的 swap 状态

使用 zramswap[编辑 | 编辑源代码]

zramswapAUR 提供一个自动化脚本,可配置一个优先度较高、默认为 20% 系统内存容量的 swap。如需让其自动在启动时执行,请启用 zramswap.service

使用 zramd[编辑 | 编辑源代码]

zramdAUR 默认使用 zstd 压缩自动配置 zram,可通过位于 /etc/default/zramd 的文件修改其配置。通过启用 zramd.service 可让其在启动时自动运行。

提示与技巧[编辑 | 编辑源代码]

查看 zram 状态[编辑 | 编辑源代码]

使用 zramctl(8)。示例:

$ zramctl
NAME       ALGORITHM DISKSIZE  DATA  COMPR  TOTAL STREAMS MOUNTPOINT
/dev/zram0 zstd           32G  1.9G 318.6M 424.9M      16 [SWAP]
  • DISKSIZE = 32G: 该 zram 设备最多会存储 32 GiB 的未压缩数据
  • DATA = 1.9G: 目前, 该 zram 设备上存储着 1.9 GiB (未被压缩的) 数据
  • COMPR = 318.6M: 这 1.9 GiB 未被压缩的数据被压缩到了 318.6 MiB
  • TOTAL = 424.9M: 包含元信息在内,这 1.9 GiB 未压缩的数据使用了 424.9 MiB 的物理内存

多个 zram 设备[编辑 | 编辑源代码]

初始情况下,加载 zram 模块会创建一个 /dev/zram0 设备。

如果您需要更多的 /dev/zram 设备,使用 num_devices 内核模块参数指定设备的量,或在之后按需添加它们

优化 zram 上的 swap[编辑 | 编辑源代码]

介于 zram 与磁盘 swap 的行为不同,可以配置系统的 swap 以充分利用 zram 的优势:

/etc/sysctl.d/99-vm-zram-parameters.conf
vm.swappiness = 180
vm.watermark_boost_factor = 0
vm.watermark_scale_factor = 125
vm.page-cluster = 0

该配置的解释:

这些值与Pop!_OS 中使用的值相同。这条 GitHub 上 Pop!_OS 的 PR 同时链接到了r/Fedora 上一些用户所进行的测试,结果显示 vm.page-cluster = 0 是较为合适的值。此外,他们也发现建议使用较高的 swappniess,这与内核文档中的建议相符。

"默认情况下该值为 60。对于像 zram 或 zswap 这样在内存中的 swap,以及一些混合式的、在相较文件系统来说更为快速的设备上 swap 的配置,应当考虑 100 以上的值。例如,若 swap 设备上的随机读写平均快于文件系统上随机读写的 2 倍,则 swappiness 值应为 133 (x + 2x = 200, 2x = 133.33)。"

在配备硬盘驱动器的系统上,在 zswap 设备上的随机读写会比在文件系统上的读写快若干数量级,因此 swappiness 应为 200 左右。甚至是在配备高速固态硬盘的系统上,较高的 swappiness 值也是理想的。

将 zram 用于非 swap 用途[编辑 | 编辑源代码]

Zram 也可以被用作普通的内存块设备,像是占用较少物理内存,但性能略微下降的 /dev/ram 设备。然而,有几个问题需要注意:

  • 无分区表支持(不会自动创建 /dev/zramxpy)。
  • 块大小固定为 4 kiB。

显然,可以通过在 zram 上叠加回环设备来绕过这一问题。使用 losetup,可以使用 -b 参数指定块大小,使用 -P 参数处理分区表并自动创建分区回环设备。

# zramctl -f -s NG
/dev/zramx

将磁盘镜像复制到新创建的 /dev/zram

本文或本章节的事实准确性存在争议。

原因: 为什么块大小要设为 512?(在 Talk:Zram 中讨论)


# losetup -f -b 512 -P /dev/zramx
# ls /dev/loop*
/dev/loop0 /dev/loop0p1 /dev/loop0p2
# mount /dev/loop0p1 /mnt/boot
# mount /dev/loop0p2 /mnt/root
注意:
  • zram 设备编号取决于已有的 zram 设备,其大小应足以存放磁盘镜像。
  • ls /dev/loop* 的输出结果取决于磁盘镜像中的内容。

另请参阅[编辑 | 编辑源代码]