一台内存不大的常开机器,偶尔同时处理文件索引和压缩任务,交互就会明显变慢。我没有先照抄一组“通用参数”,而是记录任务耗时、内存压力和交换活动,再试一块适度大小的 zram。目标是让短暂的内存尖峰更平稳,不是把已经长期超载的机器变成大内存服务器。

先看压力来自哪里

建立修改前的记录
free -h
swapon --show
vmstat 1 10
cat /proc/pressure/memory
cat /proc/sys/vm/swappiness

free 的 available 比单看 free 更接近可用余量,因为文件缓存通常可以回收。vmstat 第一行多为启动以来的平均值,后面的采样才适合观察当前负载。连续的换入换出、内存压力等待和任务变慢放在一起看,才有判断依据;交换空间里有旧页面,本身不表示机器正在发生严重问题。

zram 把交换页面压缩后保存在内存中,用计算开销换取一定空间。压缩率取决于数据,有些页面压不小;它自身也要占元数据和分配开销。因此设备的逻辑容量不等于已经消耗的物理内存,更不等于额外获得同样大小的真实内存。负载持续增长时,仍可能触发内存不足处理。

手动开一个 zram 设备

先检查是否已有发行版服务管理 zram。如果 zramctl 或 swapon --show 已列出相关设备,就沿用原来的管理方式,不再叠加。下面适用于有内核 zram 支持、已安装相关管理工具,且没有现有 zram 设备的测试主机。先记录原有交换配置,不要急着关闭磁盘交换。

一次重启前有效的手动测试
sudo modprobe zram
zdev=$(sudo zramctl --find --size 1G)
printf '%s\n' "$zdev"
sudo mkswap "$zdev"
sudo swapon --priority 100 "$zdev"
swapon --show
zramctl

务必先读 zdev 的输出,确认它是刚分配的 zram 设备,再执行格式化交换区的命令。这里用一 GiB 的逻辑容量作为起点,压缩算法先保留内核默认值。优先级较高的交换区通常优先使用;既有磁盘交换的优先级也要从输出里核对,不能只假定它一定更低。

这个操作没有写入开机配置,适合做前后对照。一次只改变一个变量,我会先观察 zram 开启后的表现,再调整交换倾向。如果已经有多个自动管理组件,手工创建设备反而会让启动行为难以解释,应该回到那套组件的配置里修改。

swappiness 控制什么

在现代内核中,vm.swappiness 的范围是零到二百,用于影响匿名页面与文件页面回收的相对倾向。它不是“内存使用达到百分之多少就开始交换”的阈值。零也不应理解为绝对禁止交换。对于压缩内存交换,较高的值有时合理,但是否合适仍取决于处理器、存储和负载。

保存旧值,临时改为一个中间值
old_swappiness=$(cat /proc/sys/vm/swappiness)
sudo sysctl -w vm.swappiness=100

# 用相同的索引任务观察一轮,再回到原值
sudo sysctl -w "vm.swappiness=$old_swappiness"

我会在同一个终端里保留旧值,分别记录相同任务下的完成时间、响应延迟、CPU 占用和压力指标。缓存冷热也会影响结果,所以不把单次运行当结论。zramctl 中的原始数据量、压缩数据量和总内存占用要一起看,总占用还包含压缩数据之外的开销。

记录结果与撤销

如果压缩带来的 CPU 开销让任务更慢,或者压力仍然长时间居高不下,就回到应用并发数和工作集大小。调整参数只能改变取舍,不能替代容量规划。我也不会为了得到好看的“空闲内存”数字,定时清理文件缓存;那会打乱测量,还可能增加后续读取成本。

只撤销本次手动创建的设备
sudo swapoff "$zdev"
# 只有上一条成功后才执行重置
sudo zramctl --reset "$zdev"

关闭交换需要把页面迁出,要先确保有足够内存或其他交换容量,并选低负载时段。若关闭失败,不继续重置设备。测试结束后,将旧参数和观察结果记下来;确实有稳定收益,再通过发行版已有的服务设置持久化,避免同一设备被两套启动流程重复初始化。