zram Swap Tuning: Compression Instead of Disk - 夜莺博客

zram Swap Tuning: Compression Instead of Disk

Swapping to a disk on a memory-constrained server is a slow-motion outage: latency goes up by orders of magnitude while the kernel thrashes. zram changes the equation by making swap live in RAM as compressed pages — pages written to the device are compressed and stored in memory, typically at a 2:1 to 3:1 ratio, which means 1 GiB of swap costs only a few hundred megabytes of RAM. Done well it prevents out-of-memory kills without a disk involved. Done badly it makes the machine slower than having no swap at all. This guide covers the sizing rules and the configuration that keeps it honest.

Sizing: two times RAM, no more

The kernel documentation is explicit that there is little point creating a zram device larger than twice the size of memory, because a 2:1 compression ratio is what to expect. A device that is 1.5× RAM gives you roughly 3 GiB of effective swap on a 4 GiB machine at a realistic ratio; a device that is 8× RAM consumes metadata for capacity you can never actually back with memory.

Rule Value Why
Device size ≈ 2× RAM, or RAM + a margin Matches achievable compression ratio
Compression lz4 for speed, zstd for ratio Swap latency matters more than a few percent
mem_limit Set it to bound worst-case RAM use Prevents zram consuming all memory with incompressible data
Swap priority Higher than disk swap zram is dramatically faster than any disk

Bringing it up by hand

modprobe zram
# size and algorithm; the algorithm must be chosen before use
zramctl /dev/zram0 --size 6G --algorithm lz4
mkswap -L zram-swap /dev/zram0
swapon -p 100 /dev/zram0

# verify with the kernel's own accounting
cat /sys/block/zram0/mm_stat
#   orig_data_size  compr_data_size  mem_used_total  mem_limit  mem_used_max ...
zramctl
swapon --show

Compare orig_data_size (uncompressed) with compr_data_size (compressed) to see your real ratio, and watch mem_used_total to see what zram is actually costing in memory. If the ratio is close to 1:1 the data is incompressible and zram is pure overhead for that workload.

Persisting it with zram-generator

# /etc/systemd/zram-generator.conf.d/zram0-swap.conf
[zram0]
zram-size = ram / 2
compression-algorithm = zstd
swap-priority = 100
fs-type = swap

systemctl daemon-reload
systemctl start dev-zram0.swap
swapon --show

With no configuration at all, a bare [zram0] stanza gives you a swap device sized at half of RAM (capped at 4 GiB), which is a sensible default on small machines. On larger hosts, prefer an explicit formula: for a 64 GiB machine the useful zram swap is a few gigabytes of overflow protection, not 32 GiB of it.

Multi-compression and recompression

With CONFIG_ZRAM_MULTI_COMP, zram supports a primary algorithm plus up to three secondary ones. The idea is that a faster algorithm handles the write path, and idle or poorly compressed pages are later recompressed with a better algorithm — trading CPU on cold data for memory savings.

# primary: lz4 for write latency; secondary: zstd for cold pages
echo "algo=zstd priority=1" > /sys/block/zram0/recomp_algorithm
echo "priority=1 level=8" > /sys/block/zram0/algorithm_params
# trigger recompression of pages at or above 4K
echo 4096 > /sys/block/zram0/recompress

Always specify priority explicitly rather than relying on the algorithm name — the kernel documentation warns that the same algorithm at different priorities can be resolved unexpectedly otherwise. Recompression is a background housekeeping activity; run it when the machine is not peaking, or let the idle-page path handle it.

Is zram actually helping?

vmstat 5
cat /proc/pressure/memory
cat /sys/block/zram0/mm_stat
systemd-cgtop --order=memory

Look for three signals: memory pressure (PSI) falling after enabling zram, a compression ratio around 2:1 or better, and si/so in vmstat showing swap activity that is being served without disk I/O. A machine where zram is used heavily on a memory-hungry workload will be slower than one with enough RAM — zram is a way to avoid catastrophic OOM kills, not a substitute for memory. The right cadence is: enable zram as protection, keep PSI under observation, and treat sustained memory pressure as the trigger for a capacity change rather than a reason to enlarge the compressed device indefinitely.

Sizing arithmetic for real machines

The kernel's own advice — never much more than twice RAM — comes from the assumption of a 2:1 compression ratio. That ratio is workload-dependent, and knowing yours makes the sizing decision concrete rather than superstitious.

Machine zram size Expected compressed footprint Comment
4 GiB VPS 4-6 GiB ~1.5-2.5 GiB Protects against OOM on bursts
16 GiB server 8-16 GiB ~3-6 GiB Sized so it never needs all of it
64 GiB host 8-16 GiB ~3-6 GiB Overflow protection, not memory expansion
512 MiB container host 1 GiB ~300-500 MiB Use with a cgroup memory limit in mind

The number that keeps you honest is mem_used_max: if it approaches the configured mem_limit, zram is holding a large share of system memory in compressed form, which means the machine is genuinely short of RAM. At that point the correct action is to add memory, not to enlarge zram, because the compression path costs CPU on every fault and the workload is already paying a penalty for being unable to fit.

Choosing the algorithm with evidence

# what does the kernel support, and what is selected now?
cat /sys/block/zram0/comp_algorithm
# lzo [lz4] lz4hc zstd deflate  <-- brackets mark the active algorithm

# measure the ratio and the CPU cost for your real workload
zramctl --output-all
cat /sys/block/zram0/mm_stat
vmstat 1 10

The practical guidance: lz4 for server swap, zstd when memory pressure is the dominant problem and CPU headroom exists, deflate rarely. Swap decompression happens on a page fault, in the middle of a latency-sensitive path, so a faster algorithm is often worth a slightly worse ratio — especially on virtual machines where the hypervisor's CPU steal is already a factor. If you enable multi-compression with a secondary algorithm, use it for cold pages rather than as a replacement for the primary choice, and give the recompression work a low-priority opportunity to run (or trigger it manually during a quiet period).

Interaction with other memory features

zram does not exist in isolation, and several common configurations defeat each other.

zram and zswap together. Both compress pages, and running them simultaneously means pages are decompressed and recompressed more than once. Choose one: zram as a swap device, or zswap as a compressed cache in front of disk swap.

zram and cgroup limits. In containers, the cgroup's memory limit governs eviction; if the container's limit is small and zram is the host's swap, a container close to its limit will swap into compressed memory it cannot see as its own. Test with the real limits in place, not on a host with memory to spare.

zram and overcommit. With generous overcommit, applications reserve memory they never touch; under pressure, the pages they do touch are the ones being compressed. Monitoring page-fault latency is the honest way to tell whether zram is absorbing a spike or merely moving the cost around.

# what is actually swapping, and is it helping?
cat /proc/vmstat | grep -E "pswpin|pswpout|pgmajfault"
cat /proc/pressure/memory
perf stat -e page-faults -p $(pgrep -d, postgres) sleep 10 2>&1 | tail -5

Disabling it again: when zram is the wrong answer

swapoff /dev/zram0
echo 1 > /sys/block/zram0/reset
systemctl stop systemd-zram-setup@zram0.service 2>/dev/null
zramctl

Turn it off when the evidence says it is costing more than it saves: high CPU in the compressor paths, page-fault latency spikes that correlate with swap activity, or a compression ratio near 1:1 (which means the workload's data does not compress). The most common case is a machine running a memory-hungry application whose data is already compressed — file servers and log processors with compressed archives — where zram provides capacity on paper and latency in practice. Measuring before and after, with the same workload, is the only way to settle it, and it takes about thirty minutes.

FAQ

Should servers have swap at all? Yes, in the sense that having zram swap turns an out-of-memory kill into degraded performance. The old advice to disable swap assumes disk swap and a database with its own buffer management; small compressed swap as a safety net is a different proposition from paging a database to a spinning disk.

Does zram help virtual machines? It can, particularly on oversubscribed hypervisors, but be aware of double compression if the host also compresses memory. Measure both layers.

What about /tmp on zram? Mounting /tmp on a compressed RAM device is a legitimate use — it is dramatically faster than disk and is discarded at reboot — but it consumes memory exactly when the system is under pressure, and it makes a crash lose the data you were about to diagnose. Keep application logs off it.

How do I monitor it in Prometheus? Export mm_stat as a metric set (original versus compressed size, memory used, max used) and alert on the ratio falling below about 1.5:1 or mem_used_max approaching mem_limit. Those two conditions are the actionable signals.

Quick reference: enable, inspect, disable

# enable (systemd generator — persistent across reboots)
printf '[zram0]\nzram-size = ram / 2\ncompression-algorithm = zstd\nswap-priority = 100\n' \
  > /etc/systemd/zram-generator.conf
systemctl daemon-reload && systemctl start dev-zram0.swap

# inspect
zramctl
cat /sys/block/zram0/mm_stat          # original vs compressed vs memory used
cat /sys/block/zram0/comp_algorithm
vmstat 1 5

# disable
swapoff /dev/zram0 && echo 1 > /sys/block/zram0/reset && zramctl

Keep the reset step in the disable procedure: writing to reset reclaims the device's memory immediately, which is exactly what you want if you are disabling zram because it was consuming more RAM than it saved. Without the reset, the device lingers with its allocations intact and your "fix" does not free anything.

Setting the swap priority correctly

Give zram a higher priority than any disk swap so the kernel prefers it: swapon -p 100 /dev/zram0 for the compressed device, and a lower priority on a disk swap partition used only as an overflow. With equal priorities the kernel interleaves the two, which reintroduces the disk latency zram exists to avoid.

Related Reading

Related reading: ZFS ARC Size Tuning on Linux, Linux NIC Ring Buffer and Coalescing Tuning, Docker macvlan vs ipvlan: Container Networking

原文链接:https://docs.kernel.org/admin-guide/blockdev/zram.html