[ Content contribution] 一文说清swap,zram,zswap,交换空间和内存压缩方案
Tofloor
poster avatar
AMZ
deepin
2024-04-14 12:27
Author

先说结论:

zram就只是内存压缩技术,可以将内存的一定区域用于压缩空间,从而具有更高的内存利用率。关机无法保存数据,如果你不希望使用休眠功能,都不需要设置什么swap分区,直接设置zram来使用。
swap这个东西叫交换空间,一般有两种形态,交换分区和交换文件,只用它的话平时打开大文件也有可能写入硬盘交换空间,也可以用来休眠,断电保存工作进度。
zswapzswap是一个内核功能,它为交换页提供了一个压缩的内存缓存。原本会交换到磁盘的页被压缩并存储到内存中的存储池中。与zram 相比的区别在于,zswap与swap 设备协同工作,而zram是内存中的交换设备,不需要后备交换设备。你既要休眠就的有swap,通过调整交换率可以做到,平时别老往swap写入数据,内存压缩解决了平时开机使用的需求,只在休眠的时候数据要存到硬盘里,简直是个完美的方案。

我的终极方案是:采用btrfs+swapfile+zswap结合的方式。

注意:zswap和zram二者不可共存,使用zram时一定要关闭zswap

一.btrfs的swapfile启用:

从内核版本5.0开始支持在btrfs分区使用交换文件作为swap形态
从btrfs-progs 6.0版本之后才能通过自身磁盘工具命令来快速创建交换文件

从systemd 255版本才支持休眠到btrfs下的交换文件,可用 systemctl --version查看,因此uos专业版版本为241不可以

对于对硬盘使用没有过多要求的人实际上可以使用交换分区即可,因为即使是交换文件它也是固定占用空间的,只是具有一点灵活性,可以后期调整文件的大小。所以使用交换分区可以适应更多场景。
否则参照从前的方法来创建:https://bbs.deepin.org/post/270299

查询btrfs版本可以通过btrfs version 来查询,目前deepin23beta3是v6.3.2

btrfs version
btrfs-progs v6.3.2

这里需要注意btrfs磁盘工具在创建和使用交换文件时,存在一些局限性:

filesystem - 只能是单个硬件分区中创建
filesystem - 必须只有单个数据配置文件
subvolume - 如果包含任何活动交换文件,则无法创建快照
swapfile - 必须预先分配(即没有漏洞)
swapfile - 必须是 NODATACOW(即也是 NODATASUM,无压缩)

创建交换文件:
这个过程在系统启动状态下即可配置,无需进入live环境,@swap为独立子卷,不可用于快照
挂载父卷
sudo mount /dev/sda2 /mnt
创建 @swap子卷
sudo btrfs subvolume create /mnt/@swap
创建交换文件
sudo btrfs filesystem mkswapfile --size 8G /mnt/@swap/swapfile
输出:create swapfile /mnt/@swap/swapfile size 8.00GiB (8589934592)
启用交换文件:
sudo swapon /mnt/@swap/swapfile
激活后,该文件将出现在 /proc/swaps 中:

$ cat /proc/swaps
Filename                 Type    Size       Used      Priority
/mnt/@swap/swapfile      file    8388604    0         -2

前面的设置是临时性启用交换文件,可以通过fstab永久启用
编辑:sudo nano /etc/fstab 增加以下内容,uuid换成你的

#将子卷@swap挂载到/swap,进一步把/swap/swapfile这个文件挂载到swap,这里的处理很多资料都没写具体
UUID=0a79ef53-4ea9-4cdb-9b5e-5b7fb8ff0c64 /swap btrfs subvol=@swap 0 0
/swap/swapfile none swap sw 0 0

启用休眠到交换文件:
启用交换文件后,交换文件可用于休眠,不过这可不简单,你即使看到deepin重启界面有休眠按钮了,但任然会出错,无法正常休眠,这里需要进一步设置
在休眠之前,必须将恢复偏移量写入文件 /sys/power/resume_offset 该值是设备上的物理偏移量
Btrfs文件系统使用逻辑和物理之间的映射地址,但在这里,物理仍然可以映射到一个或多个特定设备的物理块地址。这是特定设备的物理偏移量,适合作为恢复偏移。
从btrfs-progs 6.1 版开始,有一个命令可以直接查询该偏移量,你说有些发行版不更新btrfs-progs像话吗?

$ sudo btrfs inspect-internal map-swapfile /mnt/@swap/swapfile
Physical start: 183341248512
Resume offset:      44761047

为了编写一些脚本和方便起见,选项 -r 将只打印偏移量,获得一个唯一输出:

$ sudo btrfs inspect-internal map-swapfile -r /mnt/@swap/swapfile
44761047

sudo nano /sys/power/resume_offset
写入:44761047这个值保存即可

非btrfs文件系统的情形可以使用如下命令获得偏移量值,btrfs使用该命令是不准确的:

sudo filefrag -v /swap/swapfile

取图中这个位置的值即可
image.png

但是上面这个文件重启就会失效,如何永久固化呢?

重点来了,使将以下参数加入到两个地方

sudo nano /etc/initramfs-tools/conf.d/resume
写入:resume=UUID=0a79ef53-4ea9-4cdb-9b5e-5b7fb8ff0c64 resume_offset=44761047
刷新配置 
sudo update-initramfs -c -k all
sudo nano /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="splash quiet resume=UUID=0a79ef53-4ea9-4cdb-9b5e-5b7fb8ff0c64 resume_offset=44761047"
刷新配置
sudo update-grub

二.zswap的应用:

关闭 zswap
sudo sh -c 'echo 0 > /sys/module/zswap/parameters/enabled'
开启 zswap
sudo sh -c 'echo 1 > /sys/module/zswap/parameters/enabled'

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/zpool:z3fold
/sys/module/zswap/parameters/accept_threshold_percent:90

其它参数参考 https://docs.kernel.org/admin-guide/mm/zswap.html

每个设置都可以在运行时通过 sysfs 接口进行更改。作为示例,要更改 compressor 参数

sudo echo zstd > /sys/module/zswap/parameters/compressor

使用内核引导参数持久化更改:

zswap.enabled=1 zswap.compressor=zstd zswap.max_pool_percent=20 zswap.zpool=z3fold

比较简单的方式是通过grub引导时传递内核参数:

sudo nano /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="splash quiet 跟着加到这里面 zswap.compressor=zstd zswap.enabled=1"

之后 sudo update-grub即可

同时我们还需要把压缩工具等放到内核模块里写入

sudo nano /etc/initramfs-tools/modules

#写入
zstd
zatd_compress
z3fold

执行 sudo update-initramfs -c -k all

交换值(Swappiness)

你可以通过此命令查看当前的交换值,deepin/uos都被预设为10,而默认值应为60,Swappiness 的值可以是 0 到 200 之间 (在Linux内核版本低于5.8时最大值为100)

sysctl vm.swappiness

你可以在内存占用的环境下通过临时改变交换值来观察测试。

sysctl -w vm.swappiness=10

最终通过写入文件参数来永久生效

文件由sysctl.d管理,按顺序的优先级生效,我这里挖出deepin/uos在最低优先级路径做了相关配置

/etc/sysctl.conf
/etc/sysctl.d/*.conf
/run/sysctl.d/*.conf
/usr/local/lib/sysctl.d/*.conf
/usr/lib/sysctl.d/*.conf

查看deepin/uos相关配置

sudo nano /usr/lib/sysctl.d/deepin.conf

#这个参数用于控制交换值,数字越小则优先使用内存,减少内存的交换,从而提升一些系统上的响应度;
vm.swappiness=10
#这个参数控制内核回收 VFS 缓存的程度,增大数值会增加回收 VFS 缓存的频率,最好不要让文件系统太过于疲劳控制在50以下
vm.vfs_cache_pressure=40

使更改生效

sudo sysctl -p

重点阐述: swappiness此参数控制用于定义内核相对于页面缓存和其他缓存换出匿名内存的积极程度。增加该值会增加交换量。默认值为 60

减小该值则优先使用内存,减少内存对swap的交换,从而提升一些系统上的响应度,适合需要内存快速响应的这类工作,对内存占用不敏感的人群。这类人群可以适当划出一部分内存做zram,将 swappiness值设为几乎为0,swap将只用于休眠。

增大 swappiness值,将提升交换的积极性,毕竟是写入硬盘,I/O性能会相比内存会降低,内存将大部分用于实际的工作,而swap则用于存放缓存数据,这种配置方法则适合常常使用虚拟机、常常编辑几万行xls文件、常常浏览器开20个标签以上的用户。这类用户不太注重io的及时性,而更在乎能稳定持续的工作不会卡死,建议为swap分区划分更多的空间,对于服务器最好不要交换swap业务稳定最重要,性能最重要,对于个人PC机默认的60可能是个好事。

因此 swappiness值是权衡之下的结果,找到自己的平衡点最重要!

请注意,换出的数据越多,系统在需要时换回数据所需的时间就越长。

三.内存压缩的启用

我的终极方案说完了,下面说说zram在debian系里的启用,由于大多数内核默认开启了zswap的配置,要启用zram请设置内核参数 zswap.enabled=0来禁用zswap

zram-tools 或者 systemd-zram-generator 软件包可用于自动设置 zram 设备,uos专业版本有zram-tools而deepin有后者systemd-zram-generator

uos的方式:
安装zram-tools并启动相应服务:
sudo apt install zram-tools
默认情况下,zRAM使用的压缩算法是lzo,如果想使用其他算法或修改zRAM的大小,我们可以修改配置文件/etc/default/zramswap
sudo nano /etc/default/zramswap

#压缩算法选择,注意系统必须安装这些压缩工具
#压缩速度:lz4 > zstd > lzo
#压缩率:zstd > lzo > lz4
ALGO=zstd
#指定用于zram的RAM量,基于可用内存总量的百分比,这优先并覆盖下面的SIZE
SIZEPERCENT=70
#指定应该用于的静态RAM量单位MiB中,如果上面设置了百分比,这条将不生效,也可以注释掉
SIZE=8192
#指定交换设备的优先级,数字越大=优先级越高,这应该高于硬盘swaps的优先级
PRIORITY=100
#建立几个zram设备,默认cpu内核几个就创建几个,以此控制数量
#CORES=1

配置好以上参数启用服务即可:
sudo service zramswap reload

可以通过以下命令查看当前用于swap的zram
swapon -s

deepin的方式:
先安装
sudo 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;也可以设置为4G、512M这样的值)

详细扩展参数看:https://github.com/systemd/zram-generator

启用服务:

systemctl daemon-reload
systemctl start /dev/zram0

调用 zramctl 或 swapon 以确认设备已创建并正在使用中。

$zramct
lNAME       ALGORITHM DISKSIZE DATA COMPR TOTAL STREAMS MOUNTPOINT
/dev/zram0 lzo-rle       4.8G   4K   80B   12K       4[SWAP]

注意:在动完磁盘和相关操作重启之前一定要更新一下initramfs

sudo update-initramfs -c -k all

截图_gpartedbin_20240627190045.jpg

截图_deepin-system-monitor_20240414134910.png

以上代表了我个人对此方案的最终理解,不使用btrfs的伙伴也一样可以搞起,举一反三!

完结!

Reply Favorite View the author
All Replies
1 / 2
To page
感恩的心
deepin
2024-04-14 12:41
#1

内容太硬,收藏了慢慢消化

Reply View the author
阿尼樱奈奈
Moderator
2024-04-14 12:50
#2

135349106551284.jpg

Reply View the author
阿尼樱奈奈
Moderator
2024-04-14 12:52
#3

等等,sudo update-geub?
IMG_20240414_125236.jpg

Reply View the author
花雨落逝
Moderator
2024-04-14 12:53
#4

好好好,你噎到我了,你负责!(doge

Reply View the author
waittingsummer
deepin
2024-04-14 12:56
#5
插个眼,等有长点的时间再用电脑看
Reply View the author
AMZ
deepin
2024-04-14 12:56
#6
阿尼樱奈奈

等等,sudo update-geub?
IMG_20240414_125236.jpg

奶奶的我正改的了

Reply View the author
buyike
deepin
2024-04-14 13:05
#7

这个必须点个赞了。

Reply View the author
AMZ
deepin
2024-04-14 13:06
#8
buyike

这个必须点个赞了。

加精应该

Reply View the author
忘记、过去
deepin
2024-04-14 13:20
#9

sweat 后排提醒,btrfs 文件系统玩儿 swapfile,如果还想用 timeshift 或者 snapper 备份快照,就必须把 swap 文件放到不需要备份的子卷里面(比如帖子里创建了 @swap 子卷)。


不然的话,如果直接放在需要快照的子卷,会在创建快照的时候失败(提示设备正在被写入啥的)......要是像我一样,哪天需要恢复快照了,突然发现一个快照都没建出来就搞笑了......

Reply View the author
AMZ
deepin
2024-04-14 13:57
#10
忘记、过去

sweat 后排提醒,btrfs 文件系统玩儿 swapfile,如果还想用 timeshift 或者 snapper 备份快照,就必须把 swap 文件放到不需要备份的子卷里面(比如帖子里创建了 @swap 子卷)。


不然的话,如果直接放在需要快照的子卷,会在创建快照的时候失败(提示设备正在被写入啥的)......要是像我一样,哪天需要恢复快照了,突然发现一个快照都没建出来就搞笑了......

没错,版主提醒的对,我在文中两处提及,希望伙伴们看得到

Reply View the author
TXOS-C.User
deepin
2024-04-14 15:08
#11

大师级教程啊,like

Reply View the author
AMZ
deepin
2024-04-14 16:56
#12
TXOS-C.User

大师级教程啊,like

过誉了

Reply View the author
andot
deepin
2024-04-14 22:11
#13

楼主写的非常详细,应该加个精。

请教楼主个问题,我物理内存是 64G,如果需要休眠的话,使用 zswap + swapfile 的方式,是否需要将 swapfile 设置为大于 64G。我之前觉得 swap 分区和 swapfile 太占磁盘空间了,所以直接用了 zram 做 SWAP,优点是省磁盘空间,缺点是失去了休眠功能,现在电脑不用了只能直接选择待机或关机。

Reply View the author
AMZ
deepin
2024-04-15 00:23
#14
andot

楼主写的非常详细,应该加个精。

请教楼主个问题,我物理内存是 64G,如果需要休眠的话,使用 zswap + swapfile 的方式,是否需要将 swapfile 设置为大于 64G。我之前觉得 swap 分区和 swapfile 太占磁盘空间了,所以直接用了 zram 做 SWAP,优点是省磁盘空间,缺点是失去了休眠功能,现在电脑不用了只能直接选择待机或关机。

不需要相等

Reply View the author
Tent
deepin
2024-04-15 00:27
#15

mark,学习了like

Reply View the author
andot
deepin
2024-04-15 22:59
#16
AMZ

不需要相等

64G 内存,swap 分配多大空间才能支持休眠?

Reply View the author
兆兆嘟嘟嘟
deepin
2024-04-15 23:46
#17

感谢分享。

Reply View the author
AMZ
deepin
2024-04-16 07:48
#18
andot

64G 内存,swap 分配多大空间才能支持休眠?

看你平时真实内存使用率,你比如说你平时真实内存使用率达到了32个g,那你最起码得设置比他更多,最好是设置64,如果你开虚拟机或者浏览器网页开的多的话,你会发现它是往swap存数据的,因此,根据需求,你应该设置更大的,也不能单单只考虑休眠的问题

Reply View the author
AMZ
deepin
2024-04-16 07:48
#19
兆兆嘟嘟嘟

感谢分享。

搞起来好用,流畅

Reply View the author
AMZ
deepin
2024-04-16 07:51
#20
Tent

mark,学习了like

搞起搞起

Reply View the author
1 / 2
To page