将 zram 用于内存交换
时间换空间, 增加物理内存使用率.

Linux 将物理内存分为内存段,叫做页面。交换(swap)是指内存页面被复制到预先设定好的硬盘空间(即交换空间)的过程,目的是释放这份内存页面。物理内存和交换空间的总大小是可用的虚拟内存的总量。交换空间可以是磁盘的一个分区,也可以是一个文件。用户可以在安装时或安装后的任何时候创建交换空间。交换空间有两种用途:一是将虚拟内存扩大到超过已安装的物理内存(RAM)的容量;二是用于 suspend-to-disk 支持。

使用 swap 扩展虚拟内存是否有好处取决于物理内存的使用情况。如果物理内存不足以支撑日常使用全部的程序的话(如日常使用时内存占满导致卡顿、死机),使用 swap _也许_会有些帮助。这样可以避免 out of memory conditions —— Linux 内核 OOM Killer 机制将尝试通过杀进程的方式来自动释放内存。如果想让虚拟内存足够使用,就需要添加相应的差值(或更多)作为交换空间。

由此可见,对于一些小内存设备,使用 swap 是较为必要的,可以扩展内存,避免一些内存不足导致程序停止甚至无法启动的情况。

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

说到这里不得不提一下 zwsap。zswap 是一个内核功能,它为交换页提供了一个压缩的内存缓存。原本会交换到磁盘的页被压缩并存储到内存中的存储池中。一旦池已满或内存耗尽,最近最少使用的(LRU)页就会被解压缩并写入磁盘,就好像它没有被拦截一样。将页解压缩到交换缓存后,可以释放池中的压缩版本。与 zram 相比的区别在于,zswap 与 swap 设备协同工作,而 zram 是内存中的交换设备,不需要后备交换设备。

将 zram 这种内存压缩技术用于 swap,可以避免与磁盘这种速度较慢设备的进行 I/O,用富裕的计算性能,换取 swap 所需的磁盘空间,更好地利用物理内存自身;而在固态硬盘普及的今天,这么做也可以避免开启 swap 后对磁盘的读写。

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

例如,考虑一个具备 32 GiB 内存的系统,其上配置了容量为 64 GiB 的 zram。假设 zstd 能够实现 1:4 的压缩比率,当被全部占用时,该 zram 块被压缩后在物理内存中占用的大小将在 16 GiB 左右。下面用具体例子来向读者说明使用 zram 能在原本可用内存上带来的提升:

  • 当内存和 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 上的交换空间的尝试。

要启用 zram 并将其用于 swap 其实很简单。这里只介绍使用 systemd-zram-generator 的方式,其余详情请参见 zram 在 Arch Linux Wiki 上对应的页面。

开始之前,先 确保禁用 zswap,方法这里不再赘述。

在 Debian 系发行版上通过 apt 安装 systemd-zram-generator

apt install systemd-zram-generator

 之后查阅并修改 /etc/systemd/zram-generator.conf 这个配置文件:

[zram0]
compression-algorithm = zstd
zram-size = ram / 2
swap-priority = 100

这里创建了一个使用 zstd 压缩、大小为所有可用内存容量一半的 zram swap 设备(ram / 2 表示大小为 RAM 大小的 1 / 2;也可以设置为 G 、512M 这样的值)。

之后应用修改并启动即可。

systemctl daemon-reload
systemctl start systemd-zram-setup@zram0

可使用 zramctl(8) 命令,或是通过查阅 [email protected] (等) 实例的 单元状态,来检查所配置的 /dev/zramN 设备的 swap 状态。zramctl 命令的输出以及内容的解释大致如下:

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

总之,使用 zram,可以用富余的运算资源,换取内存的高效利用,同时避免换出到磁盘时,对磁盘的过多写入。


Last modified on 2023-10-23