几行配置给内存扩容一半:我用 zram 治好了老卡死的机器

📅 2026/6/27 4:03:04
几行配置给内存扩容一半:我用 zram 治好了老卡死的机器
我这台机器 32G 内存、i7-10700CPU 大多数时候闲着但内存一吃紧就卡死。只用几行配置我把内存的一半划给 zram 当压缩 swap把用不上的 CPU 换成更耐用的内存。配置时在 Ubuntu 22.04 上踩了一个坑照网上的新语法写zram 只给了我 4G。这篇记录从问题、原理、配置到踩坑修复的完整过程。一、我的问题我的机器是 Ubuntu 22.04.5、内核 6.831 GiB 内存标称 32GCPU 是 i7-1070016 个线程。平时开着浏览器、编辑器和几个容器内存一冲高就卡死鼠标都拖不动要等十几秒才缓过来。但同一时间 CPU 基本是闲的。先看了内存和 swap$ free -h total used free shared buff/cache available Mem: 31Gi 8.6Gi 11Gi 909Mi 10Gi 21Gi Swap: 2.0Gi 0B 2.0Gi $ swapon --show NAME TYPE SIZE USED PRIO /swapfile file 2G 0B -2只有一个 2 G 的磁盘 swapfile 在兜底。内存一紧内核就往这块慢盘上倒页一旦开始来回换页thrashing整机就卡住。swappiness是默认的 60没有 zramzswap也没开。思路很直接内存不够、CPU 有余那就用 CPU 换内存——上 zram。二、zram 是什么为什么能换zram 在内存里建一块块设备写进去的数据先用压缩算法压一遍再存。把它当 swap 用内核换出的页就被压缩后留在内存里而不是写到磁盘。匿名页进程的堆栈、数据这类没有文件后备的内存通常能压到原大小的三分之一左右于是同样的物理内存能装下更多内容。代价是每次换出、换入都要花 CPU 做压缩和解压而这正是我富余的资源。图 1. zram 作为 swap 时一页内存换出/换入的数据通路全程在内存内完成。几个要点zsmalloc内核里专门的分配器把大小不一的压缩块紧凑地打包进内存页减少碎片让压缩省下的空间真正变成可用容量。压缩算法可选lz4快、压缩比一般、zstd压缩比高、稍慢等我用zstd。disksize 是逻辑容量声明 16 G 不代表占 16 G 物理内存实际占用只跟当前压缩后的数据量成正比。same-filled page整页全是同一字节最常见是全 0的页只记一个标记几乎不占内存。三、动手配置以及我踩的坑我用 systemd 的zram-generator配置驱动开机自动重建最省事。第 1 步安装。sudoaptupdatesudoaptinstall-ysystemd-zram-generator第 2 步写配置。我照搜到的教程写了下面这版——后面会看到这版是错的# /etc/systemd/zram-generator.conf 错误示范 [zram0] zram-size ram / 2 compression-algorithm zstd swap-priority 100sudosystemctl daemon-reloadsudosystemctl start systemd-zram-setupzram0.service第 3 步一看结果不对$ zramctl NAME ALGORITHM DISKSIZE DATA COMPR TOTAL STREAMS MOUNTPOINT /dev/zram0 zstd 4G 4K 64B 20K 16 [SWAP]31 G 的一半应该是约 15.5 G怎么只给了 4 G而且zstd和优先级都对——说明配置文件确实被读了单单尺寸不对。先确认配置没写错文件就是zram-size ram / 2没问题。于是去翻日志$ sudo journalctl -b | grep -i unknown key zram-generator[...]: Unknown key zram-size, ignoring.原因出来了它根本不认识zram-size这个键直接忽略了。再看版本和手册$ /lib/systemd/system-generators/zram-generator --version zram-generator 0.3.2 $ man 5 zram-generator.conf | grep -oE zram-fraction|max-zram-size|zram-size | sort -u max-zram-size zram-fraction手册里只有zram-fraction和max-zram-size没有zram-size。zram-sizeram / 2这种表达式语法是zram-generator较新版本1.x才有的写法Ubuntu 22.04 装的是 0.3.2只认老键。zram-size被忽略后它退回到默认值——zram-fraction默认 0.5、max-zram-size默认 4096MB于是min(0.5 × 31G, 4G) 4G。这就是那 4 G 的来历。坑就坑在它静默退回默认、只在日志里留一行Unknown key照抄新版教程、又不去翻 journal 的人很容易就拿着一块 4 G 的 zram 以为配好了。第 4 步改用这版认识的键# /etc/systemd/zram-generator.conf 正确 [zram0] zram-fraction 0.5 max-zram-size 16384 compression-algorithm zstd swap-priority 100zram-fraction 0.5把逻辑容量设成内存的一半max-zram-size 1638416 G把默认 4 G 的上限抬上去否则又会被砍回 4 G。重启服务sudosystemctl restart systemd-zram-setupzram0.service$ zramctl NAME ALGORITHM DISKSIZE DATA COMPR TOTAL STREAMS MOUNTPOINT /dev/zram0 zstd 15.5G 4K 64B 20K 16 [SWAP] $ swapon --show NAME TYPE SIZE USED PRIO /swapfile file 2G 0B -2 /dev/zram0 partition 15.5G 0B 100这次对了15.5 G、zstd、优先级 100排在磁盘swapfile-2前面。内核会先用 zram用满了才轮到磁盘。第 5 步提高 swappiness。zram 换页很便宜我把swappiness调高让内核更早把冷页压进 zram而不是死撑物理内存直到颠簸echovm.swappiness 150|sudotee/etc/sysctl.d/99-zram.confsudosysctl--system四、开机自启与持久化不用额外做什么。zram-generator是 systemd 生成器每次开机会按/etc/systemd/zram-generator.conf自动重建 zram swapswappiness写在/etc/sysctl.d/99-zram.conf里也是持久的。重启后zramctl直接能看到那块 15.5 G 的zram0。五、它平时占内存吗什么时候才被用到配完我有个疑问开了 15.5 G 的 zram是不是平时就吃掉了我一大块内存答案是不会。先看一眼平时空闲时的状态图 3. 内存富裕时占用 37%swap 用量为 0——zram 已就位但还没被用到此刻几乎不占物理内存。图中 Swap 总量 18.8 G zram 15.5 GiB 磁盘 swapfile 2 G。两个要点zram 不预占内存。disksize那 15.5 G 是逻辑容量zram 实际占用的物理内存只跟当前压进去的数据成正比。图里 swap 用量是 0所以 zram 此刻几乎不吃物理内存——我配出 18.8 G 的 swap 池并没有让可用内存少一点。它按内存压力随用随取不是等满了才用。内核按压力渐进回收内存越紧越会把很久没碰的冷页压进 zram腾出物理内存给活跃数据。这个过程在远没到 OOM 之前就开始所以 zram 是个提前介入的缓冲而不是最后一刻的救命稻草。swappiness 150让它在有压力时更倾向于把冷页换进便宜的 zram而不是死扛物理内存。判断系统有没有压力最直接就是看 swap 用量像图里这样接近 0就说明很宽裕。要亲眼看它工作等内存压上去比如 Memory 涨到 80% 以上再看这几项zramctl# DATA(原始) 会从 0 涨起来TOTAL 是它实占的物理内存cat/sys/block/zram0/mm_stat# 更细orig_data_size compr_data_size mem_used_total ...swapon--show# /dev/zram0 的 USED 会 0zramctl的三列是关键DATA是写入的原始数据量COMPR是压缩后大小TOTAL是含分配器开销的实际内存占用DATA / TOTAL就是实际压缩比。还有个常见误读配了 zram 后监控里 swap 用量会变活跃这是正常的——这些swap并没有离开内存判断它是否真起作用看压缩比而不是 swap 用量数字。六、zram 和 zswap 的区别顺带说一下另一个容易混淆的东西 zswap。两者都用压缩省内存但结构不同。图 2. zram 自成终点压缩数据常驻内存zswap 是磁盘 swap 前的压缩缓存池满后向磁盘回写。zram 是一块独立的内存盘不需要后备磁盘压缩数据一直在内存里填满且没有别的 swap 兜底时只能触发 OOM。zswap 是磁盘 swap 前面的一道压缩缓存必须配合磁盘 swap页先压进内存池池满时按冷热把最旧的页解压、写回磁盘。维度zramzswap是否需要后备磁盘不需要需要真实 swap 分区压缩数据存放常驻内存内存池满了写回磁盘池满之后触发 OOM向磁盘回写溢出适用swap 需求小且稳定swap 需求大或不可预测我的场景是想要一块快的、自给自足的内存 swap所以选 zram。七、适用、注意和实际效果适合用 zram 的情况就是我这种物理内存紧、CPU 有余量。几点注意不可压缩数据会白耗 CPU。已压缩的媒体、加密数据、随机数据压不动压缩比接近 1。这类负载可以配writeback把它们写回磁盘。zram 只能推迟 OOM不能消除 OOM。我保留了默认开着的systemd-oomd让它在内存真耗尽前杀掉失控进程避免硬锁死。CPU 满载时会抢算力。zram 的前提是内存紧、CPU 闲。我的 CPU 大多数时候闲着不亏。实际效果实话说zram 不是真的加内存而是让现有内存靠压缩多装一些、并把 swap 变快。配完之后内存冲高时不再卡死成那样——以前是往 2 G 磁盘 swap 上颠簸现在是压进 zram、微秒级就能取回。effective 容量大概多出 8–12 G 量级。但如果工作负载常驻就要超过 32 G唯一的真解还是加内存条zram 是缓冲不是无中生有。参考文献zram: Compressed RAM-based block devices — The Linux Kernel documentationsystemd/zram-generatorzram — ArchWikiChris Down, “Debunking zswap and zram myths” (2026)zswap — Wikipedia