Skip to content
← ENGINEERING NOTES
LINUX7 min read

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.

bash
# 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=zstd
Enable and inspect zswap at runtime (as root)

Two 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.

bash
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 --show
A zram swap device from scratch (as root)

The 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.

bash
cat <<'CONF' | sudo tee /etc/sysctl.d/99-compressed-swap.conf
vm.swappiness = 133
vm.page-cluster = 0
CONF
sudo sysctl --system
Make the tuning persistent

QUICK 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.

bash
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
Real compression ratio from mm_stat, plus pressure
›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

  1. zswap — Linux kernel source tree
  2. zram: Compressed RAM-based block devices — Linux kernel source tree
  3. 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

linuxzswapzramswapmemoryswappinesssysfs

RELATED

ENGINEERING NOTES

Things we built.Things we broke.Things we learned.