跳转至内容

zram

来自 ArchWiki

zram(原名 compcache)是一个 Linux 内核模块,用于在 RAM 中创建压缩块设备,即一个具有实时磁盘压缩功能的 RAM 磁盘。使用 zram 创建的块设备随后可用作交换空间或通用 RAM 磁盘。zram 最常见的两种用途是存储临时文件(/tmp)和作为交换设备。最初,zram 仅具有后者功能,因此最初被命名为 "compcache"("compressed cache",压缩缓存)。

作为交换空间使用

最初,创建的 zram 块设备不会预留或使用任何 RAM。只有当文件需要或想要被交换出去时,它们才会被压缩并移动到 zram 块设备中。随后,zram 块设备将根据需要动态增长或缩小。

即使假设 zstd 仅能达到保守的 1:2 压缩率(实际数据显示常见比例为 1:3),zram 仍具有在 RAM 中存储比不使用内存压缩时更多内容的优势。

  • 在配置 zram 时,zram 设备的尺寸控制的是它可以存储的最大“未压缩”数据量,而不是最大压缩后的大小。只要物理 RAM 上的压缩后大小不超过系统的物理 RAM 容量,你就可以将 zram 的尺寸配置为等于甚至大于系统的物理 RAM 容量。
  • 如果相关的 zswap 内核功能保持启用,它将妨碍 zram 的有效使用。这是因为 zswap 作为 zram 之前的交换缓存,会在被驱逐的内存页到达 zram 之前对其进行拦截和压缩。尽管 zramctl(8) 的输出显示如此,但在这种情况下,zswap 的大部分功能并未被利用。因此,建议在启动前使用内核参数或 sysfs 设置永久 禁用 zswap
  • 不支持休眠到 zram 上的交换空间,即使 zram 配置了永久存储上的后备设备也不行。logind 将防止尝试休眠到 zram 上的交换空间。
提示 你可以使用 mem_limit 参数指定 zram 用于存储压缩数据的最大内存量。

一个简单的初始尺寸是系统总内存的一半。

手动设置

设置一个使用 zstd 压缩、容量为系统内存一半且优先级高于常规的 zram 设备(仅限当前会话):

# modprobe zram
# zramctl /dev/zram0 --algorithm zstd --size "$(($(grep -Po 'MemTotal:\s*\K\d+' /proc/meminfo)/2))KiB"
# mkswap -U clear /dev/zram0
# swapon --discard --priority 100 /dev/zram0

要再次禁用它,请重启或运行:

# swapoff /dev/zram0
# modprobe -r zram

关于所有步骤、选项和潜在问题的详细解释请参阅 zram 模块官方文档

若要永久生效,请使用以下章节中的某种方法。

使用 udev 规则

下面的示例描述了如何通过单个 udev 规则和 fstab 条目在启动时自动设置 zram 交换空间。无需安装额外软件包即可实现。

明确在启动时 加载模块

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

创建以下 udev 规则,并根据需要调整 disksize 属性

/etc/udev/rules.d/99-zram.rules
ACTION=="add", KERNEL=="zram0", ATTR{initstate}=="0", ATTR{comp_algorithm}="zstd", ATTR{disksize}="4G", TAG+="systemd"

/dev/zram 添加到你的 fstab 中,并设置高于默认值的优先级以及 x-systemd.makefs 选项

/etc/fstab
/dev/zram0 none swap defaults,discard,pri=100,x-systemd.makefs 0 0

使用 zram-generator

zram-generator 是一个托管在其 GitHub 组织下的 systemd 相关项目,利用了 systemd 的约定和机制。

它提供了 systemd-zram-setup@zramN.service 单元,用于自动初始化 zram 设备,用户无需手动 启用/启动 模板或其实例。参见 zram-generator(8)

要使用它,请 安装 zram-generator,并创建 /etc/systemd/zram-generator.conf,内容如下:

/etc/systemd/zram-generator.conf
[zram0]

这就足以创建一个名为 zram0 的 zram 设备,并使用默认选项(当前值请参阅 zram-generator.conf(5))。

默认情况下,zram 设备将使用 RAM 大小的一半不超过 4 GiB例如,如果你有 4 GiB RAM,它将创建 2 GiB 的 zram 设备;如果你有 8 GiB 或更多内存,它仅创建 4 GiB 的 zram 设备。

如果你想更改此设置,请使用 zram-size 参数

/etc/systemd/zram-generator.conf
[zram0]
zram-size = min(ram / 2, 16384)

这将允许 zram 设备使用总内存的一半,最高可达 16 GiB(min(x,y) 比较两个值并选取较小者)。

  • 如果你想无条件地允许 zram 设备使用一半的内存,请使用 zram-size = ram / 2
  • 对于固定大小,请使用(例如) zram-size = 8192

有关图表和更复杂示例,请参阅 zram-generator.conf(5) § EXAMPLES

要使用与内核当前默认值不同的 压缩算法,请使用 compression-algorithm

/etc/systemd/zram-generator.conf
[zram0]
compression-algorithm = lzo-rle zstd(level=3) (type=idle)

随后的算法将用于重新压缩。

所有可用选项的列表请参阅 zram-generator.conf(5)

定义配置后,运行 daemon-reload启动 你配置的 systemd-zram-setup@zramN.service 实例(N 匹配数字实例 ID,在本例中为 systemd-zram-setup@zram0.service)。

你可以通过读取 systemd-zram-setup@zramN.service 实例的 单元状态,或使用 zramctl(8)swapon(8)检查已配置的 /dev/zramN 设备的交换状态

使用 zramswap

zramswapAUR 提供了一个自动化脚本,用于设置优先级较高且默认大小为系统 RAM 20% 的交换空间。要每次启动时自动执行,请 启用 zramswap.service

技巧与提示

检查 zram 统计信息

使用 zramctl(8)。示例:

$ zramctl
NAME       ALGORITHM DISKSIZE  DATA  COMPR  TOTAL STREAMS MOUNTPOINT
/dev/zram0 zstd           32G  1.9G 318.6M 424.9M         [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 的物理 RAM

压缩算法

在创建 zram 设备 N 后,使用 cat /sys/block/zramN/comp_algorithm 来查看可用的压缩算法以及当前选定的算法(在括号中)。

使用默认选项的 linux 6.17.9.arch1-1 的结果:

lzo-rle lzo lz4 lz4hc [zstd] deflate 842

多个 zram 设备

默认情况下,加载 zram 模块会创建单个 /dev/zram0 设备。

如果你需要多个 /dev/zram 设备,请使用 num_devices 内核模块参数 指定数量,或者在之后根据需要 手动添加

优化 zram 上的交换空间

由于 zram 的行为与磁盘交换不同,我们可以配置系统的交换设置以充分发挥 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 所使用的。该 Pop!_OS GitHub 拉取请求还链接到了 r/Fedora 用户进行的一些测试,结果表明 vm.page-cluster = 0 是理想的。他们还发现较高的 swappiness 值是理想的,这与 内核文档中的建议一致

默认值为 60。
对于内存交换(如 zram 或 zswap)以及交换空间在比文件系统更快速设备上的混合设置,可以考虑 100 以上的值。例如,如果交换设备的随机 IO 平均比文件系统的 IO 快 2 倍,则 swappiness 应为 133 (x + 2x = 200, 2x = 133.33)。

在带有机械硬盘的系统上,内存设备的随机 I/O 将比文件系统的 I/O 快几个数量级,因此 swappiness 应在 ~200 左右。即使在配备快速 SSD 的系统上,高 swappiness 值也可能是理想的。

为 zram 块设备启用后备设备

zram 可以配置为将不可压缩的页面推送到指定的块设备

手动添加后备设备:

# echo /dev/sdX > /sys/block/zram0/backing_dev

要使用 zram-generator 为 zram 块设备添加后备设备,请在 /etc/systemd/zram-generator.conf 中你想要添加后备设备的 [zramX] 设备下方更新以下内容:

/etc/systemd/zram-generator.conf
writeback-device=/dev/disk/by-partuuid/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX

随后可以通过执行以下命令将不可压缩的页面推送到块设备:

# echo huge > /sys/block/zramX/writeback

将 zram 用于非交换目的

zram 也可以用作通用 RAM 后备块设备,例如一个物理内存占用较少但性能稍低地 /dev/ram。不过有一些注意事项:

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

解决此问题的明显方法是在 zram 之上叠加一个回环设备(loop device),使用 losetup,通过 -b 选项指定所需的块大小,并使用 -P 选项来处理分区表并自动创建分区回环设备。

# zramctl -f -s NG
/dev/zramx

将磁盘镜像复制到新的 /dev/zramx,然后创建回环设备。如果磁盘镜像有分区表,则回环设备的块大小必须与分区表使用的块大小匹配,通常为 512 或 4096 字节。

# 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* 的输出取决于磁盘镜像的内容。

参见

© . This site is unofficial and not affiliated with Arch Linux.

Content is available under GNU Free Documentation License 1.3 or later unless otherwise noted.