zswap vs zram: Compressed Swap on Linux
zswap vs zram on Linux: how each compresses memory, when to pick which, and the exact sysfs, swappiness and page-cluster settings to configure and measure.
BY ASHLIN DARIUS GOVINDASAMY
Your RAM is full, and Linux has two clever ways to say 'not yet': squash the cold pages instead of writing them to disk. zswap and zram both do this, and people argue about them like it is a text editor war. This zswap vs zram guide cuts through it with what the kernel documentation actually says, then gives you commands to set one up and numbers to check that it works.
Two ways to compress memory
The kernel docs describe zswap as a lightweight compressed cache for swap pages. It takes pages that are being swapped out and tries to compress them into a dynamically allocated RAM-based pool, trading CPU cycles for potentially reduced swap I/O. Crucially it sits in front of a real swap device: when the pool reaches its limit, zswap evicts pages on an LRU basis to the backing swap.
zram is different in kind. It creates RAM-based block devices named /dev/zram<id>; pages written to them are compressed and stored in memory itself. The docs list use as swap disks, but also /tmp and caches under /var. There is no disk behind it unless you configure an optional backing device, so when a zram swap device is full, it is full.
How zswap works
zswap manages its pool with zsmalloc. It keeps a mapping from the swap entry to the zsmalloc handle using an xarray per swap type. On a page fault for a swapped-out page the swapin code asks zswap to decompress it. The pool is not preallocated: it grows on demand and shrinks as compressed pages are freed. Pages whose contents are one repeated value, including zero-filled pages, are stored as a pattern with a compressed length of zero.
Policy is deliberately small. The user-controlled knob is max_pool_percent, the maximum percentage of memory the compressed pool may occupy. There is also accept_threshold_percent, a hysteresis: after the pool hits its limit, zswap refuses new pages until it has space again, which prevents pages flipping in and out of the pool. Setting it to 100 disables the hysteresis.
# Is it on? Which compressor?
cat /sys/module/zswap/parameters/enabled
cat /sys/module/zswap/parameters/compressor
# Turn it on and pick a compressor
echo 1 > /sys/module/zswap/parameters/enabled
echo zstd > /sys/module/zswap/parameters/compressor
# Cap the pool and set the refill hysteresis
echo 20 > /sys/module/zswap/parameters/max_pool_percent
echo 80 > /sys/module/zswap/parameters/accept_threshold_percent
# Stats live in debugfs
mount -t debugfs none /sys/kernel/debug 2>/dev/null
grep -r . /sys/kernel/debug/zswap/ | head -20
# Persist across boots: kernel command line
# zswap.enabled=1 zswap.compressor=zstdTwo behaviours from the docs are worth memorising. Disabling zswap at runtime stops new stores but does not drain the pool; only a swapoff faults everything back. And changing the compressor at runtime leaves existing pages in their old pool, decompressed with their original compressor until that pool empties.
How zram works
zram is configured entirely through sysfs: pick an algorithm, set a disk size, optionally cap memory, then format it as swap. The order matters. comp_algorithm cannot be changed once the device is initialised, and writing disksize is what initialises it.
modprobe zram num_devices=1
# 1) choose the algorithm BEFORE setting disksize
cat /sys/block/zram0/comp_algorithm
echo zstd > /sys/block/zram0/comp_algorithm
# 2) optional per-algorithm parameters; one write replaces ALL params
echo "algo=zstd level=3" > /sys/block/zram0/algorithm_params
# 3) size it, optionally cap real RAM use
echo 4G > /sys/block/zram0/disksize
echo 3G > /sys/block/zram0/mem_limit
# 4) activate with a priority above any disk swap
mkswap /dev/zram0
swapon --priority 100 /dev/zram0
swapon --showThe tuning knobs that matter for both
Defaults assume swap is slow. Compressed memory is not. The vm sysctl docs say swappiness expresses the rough relative I/O cost of swapping versus filesystem paging, on a 0 to 200 scale, defaulting to 60. For in-memory swap such as zram or zswap, they say values beyond 100 can be considered, with a worked example: if swap I/O is on average twice as fast as filesystem I/O, swappiness should be 133.
The second knob is page-cluster, the swap counterpart to readahead. It is logarithmic: the default of 3 reads eight pages at a time, and 0 disables swap readahead. Lower values mean lower latency for the initial fault but possibly more faults later. With a RAM-backed device there is no seek penalty to amortise, so 0 is a reasonable experiment, though the docs only say that small benefits may come from tuning it for swap-intensive workloads. Measure; do not assume.
cat <<'CONF' | sudo tee /etc/sysctl.d/99-compressed-swap.conf
vm.swappiness = 133
vm.page-cluster = 0
CONF
sudo sysctl --systemQUICK CHECK
Your zram swap device is completely full and you have no other swap. What happens to further swap-out attempts?
Which one should you use?
- You already have a swap partition or file on SSD, and want fewer writes and faster faults: zswap. The docs call out reduced life-shortening writes for SSD swap devices and lower swap I/O for overcommitted guests.
- You have no disk swap at all (SBC, diskless VM, container host): zram, since zswap needs a backing swap device.
- You want a compressed /tmp or cache directory: zram, because it is a real block device you can mkfs.
- Both on one box: possible, but you would be compressing twice. Choose one tier and give it a clear job.
- Workloads that cannot tolerate disk swap at all: zswap supports turning off writeback per cgroup with memory.zswap.writeback, though the docs warn that recurring store failures on incompressible pages can make reclaim inefficient.
Measuring: is it actually helping?
zram exposes its numbers in mm_stat: orig_data_size, compr_data_size, mem_used_total and friends, with mem_used_total including allocator fragmentation and metadata. Dividing original by used total gives you the real ratio your workload gets, not the 2:1 folklore.
awk '{ printf "orig=%.1f MiB compressed=%.1f MiB used=%.1f MiB ratio=%.2f:1 same_pages=%d huge_pages=%d\n",
$1/1048576, $2/1048576, $3/1048576, $1/($3>0?$3:1), $6, $8 }' /sys/block/zram0/mm_stat
# Is the system actually stalling on memory? (PSI)
cat /proc/pressure/memory
# Generate load and watch swap traffic
stress-ng --vm 2 --vm-bytes 90% --timeout 60s &
vmstat 2 30›Why does huge_pages matter?
In the zram stats, huge_pages counts incompressible pages. A high count means your data does not compress, and zram is spending CPU for no saving. In zswap's case the same problem shows up as rejected stores in the debugfs counters. If either is large, compressed swap is the wrong tool for that workload, and you should add RAM or fix the memory hog instead.
QUICK CHECK
You run 'echo lz4 > /sys/block/zram0/comp_algorithm' after already writing disksize. What does the documentation say?
Takeaway
- zswap is a compressed cache in front of real swap; zram is a compressed RAM disk. Pick by whether you have a disk swap to fall back on.
- Order of operations for zram: algorithm, parameters, disksize, mkswap, swapon with a high priority.
- Raise vm.swappiness above 100 only for genuinely in-memory swap, and test page-cluster 0.
- Trust mm_stat and PSI, not folklore ratios.
SOURCES
- zswap — Linux kernel source tree
- zram: Compressed RAM-based block devices — Linux kernel source tree
- Documentation for /proc/sys/vm: swappiness, page-cluster — Linux kernel source tree
Frequently asked questions
Is zswap or zram better?
Neither universally. zswap is a compressed cache in front of a disk swap device and spills to it when full, while zram is a fixed-size compressed RAM block device with no disk behind it by default. Use zswap when you have disk swap, zram when you do not or need a compressed block device.
What swappiness should I use with zram?
The kernel docs say values beyond 100 can be considered for in-memory swap, and give the formula example of 133 when swap I/O is twice as fast as filesystem I/O. Benchmark your own workload rather than copying a number.
Can I change the zram compression algorithm later?
Not on an initialised device. Select comp_algorithm before writing disksize, or reset the device and configure it again.
Does disabling zswap flush the compressed pool?
No. The docs say pages stay in the pool until invalidated or faulted back; running swapoff on the swap device forces them back into memory.
NEWSLETTER
Get the engineering notes in your inbox.
Kernels, GPUs, networks, AI infrastructure — and the things we broke along the way. No spam, one click to leave.
We store only your email address, to send you new articles. See our privacy policy.
TAGS
RELATED
Multi-Gen LRU: Stop Linux Thrashing Under Memory Pressure
Tame Linux memory thrashing with the multi-gen LRU. Check it is on, set min_ttl_ms, read the working-set histogram in debugfs and reclaim cold pages on demand.
Reading Linux PSI: Why Is My Machine Stalling?
Use Linux PSI (/proc/pressure) to tell memory, I/O and CPU stalls apart, set kernel pressure triggers in C, and chase the culprit with vmstat and bpftrace.
Linux OOM Kill With Free RAM Left? Read This
free shows gigabytes available, yet the OOM killer struck. Learn MemAvailable, slab, overcommit and oom_score_adj with commands to find out why and fix it.