$linuxjunkies
>

Linux Memory: Anonymous, File-backed, zswap

Deep dive into Linux anonymous vs file-backed pages, reclaim mechanics, vm.swappiness, zswap compression tuning, and zram setup for maximum memory efficiency.

AdvancedUbuntuDebianFedoraArch11 min readUpdated June 7, 2026

Before you start

  • Root or sudo access on the target system
  • Kernel 5.8 or later recommended (vm.swappiness 0-200 range, modern zswap defaults)
  • Basic familiarity with sysctl and reading /proc/meminfo
  • sysstat package installed for sar/vmstat extended output

Linux memory management is subtle. The kernel tracks every page of RAM and decides, under pressure, what to keep hot and what to evict or compress. Getting that decision wrong means either a sluggish desktop or a thrashing server. This guide walks through the two fundamental page types, how reclaim works, and how to tune vm.swappiness, zswap, and zram for real workloads.

Anonymous vs File-Backed Pages

Every page in RAM belongs to one of two classes:

  • File-backed pages are backed by a file on disk — executable code, shared libraries, memory-mapped data files, page cache for reads and writes. If the kernel needs the RAM, it can simply drop clean file pages (they can be re-read from disk on demand) or write dirty ones back before dropping them.
  • Anonymous pages have no file behind them. They are heap allocations (malloc), stack frames, and private mmap regions. The only place they can go when evicted is swap space.

You can inspect the split at any moment:

grep -E 'Active|Inactive|Anon|File|Swap' /proc/meminfo

The output will show Active(anon), Inactive(anon), Active(file), and Inactive(file) — the kernel's own LRU lists. Pages age from active to inactive before they become candidates for reclaim.

How Reclaim Works

The kernel runs two reclaim paths:

  • kswapd — a per-NUMA-node background thread that wakes up when free memory falls below pages_low watermark. It reclaims pages gradually to keep a small buffer of free RAM.
  • Direct reclaim — triggered synchronously when an allocation cannot be satisfied from free lists and kswapd is not keeping up. This stalls the allocating process and is expensive.

Watch whether you are hitting direct reclaim with:

vmstat 2 5

The si and so columns show swap-in and swap-out rates per second. Sustained non-zero values mean the system is reclaiming anonymous memory under pressure.

For a richer view, sar from sysstat shows page fault rates and reclaim activity over time:

sar -B 1 5

Tuning vm.swappiness

vm.swappiness controls the kernel's tendency to reclaim anonymous pages (pushing them to swap) versus reclaiming file-backed pages (dropping them from the page cache). It is not a simple swap-on/swap-off switch.

  • Range: 0–200 (kernels ≥ 5.8 extended it to 200; older kernels cap at 100).
  • Default: 60 on most distributions.
  • Higher value → prefer reclaiming anonymous pages (swap more aggressively).
  • Lower value → prefer reclaiming file cache; anonymous pages stay in RAM longer.
  • Value 0 does not disable swap; it just makes the kernel very reluctant to reclaim anonymous pages until absolutely necessary.

Check and Set Temporarily

cat /proc/sys/vm/swappiness
sysctl vm.swappiness=10

Make it Persistent

echo 'vm.swappiness=10' | sudo tee /etc/sysctl.d/99-memory.conf
sudo sysctl --system

Practical guidance: desktops with 16 GB+ RAM typically benefit from a value of 10–20, keeping interactive applications' heap in RAM. Database servers (PostgreSQL, MySQL) often do well at 10 or even 1, since their buffer pools are anonymous memory and eviction is catastrophic for latency. Servers dominated by file I/O can tolerate higher values.

zswap: Compressed Swap Cache

zswap is a kernel subsystem that intercepts pages on their way to swap, compresses them in a small RAM pool, and only writes to actual swap if that pool fills up. The result is faster swap-out/swap-in (compression in RAM beats a disk round-trip) at the cost of some CPU and a reserved chunk of RAM.

Check Whether zswap Is Active

cat /sys/module/zswap/parameters/enabled
grep -r . /sys/kernel/debug/zswap/ 2>/dev/null

Many modern distributions (Ubuntu 22.04+, Fedora 34+) enable zswap by default. If the first command returns N, you can enable it at runtime:

echo 1 | sudo tee /sys/module/zswap/parameters/enabled

For a persistent boot-time configuration, add kernel parameters. On systemd-boot or GRUB:

# Add to GRUB_CMDLINE_LINUX in /etc/default/grub:
# zswap.enabled=1 zswap.compressor=lz4 zswap.max_pool_percent=20

# Debian/Ubuntu — rebuild grub after editing:
sudo update-grub

# Fedora/RHEL:
sudo grub2-mkconfig -o /boot/grub2/grub.cfg

# Arch (systemd-boot — edit the loader entry directly):
sudo nano /boot/loader/entries/*.conf
# append to the options line: zswap.enabled=1 zswap.compressor=lz4 zswap.max_pool_percent=20

Key zswap Parameters

ParameterDefaultNotes
compressorlzo-rle or zstdlz4 is fastest; zstd gives better ratio. Check cat /sys/module/zswap/parameters/compressor.
max_pool_percent20Percentage of total RAM the zswap pool can use. 10–20 % is typical.
zpoolzsmallocAllocator for compressed pages. zbud uses less CPU; zsmalloc packs more densely.

Tune compressor at runtime (no reboot needed if the module is loaded):

echo lz4 | sudo tee /sys/module/zswap/parameters/compressor
echo 15 | sudo tee /sys/module/zswap/parameters/max_pool_percent

zram: Compressed RAM Swap

zram creates a block device backed entirely by RAM, formatted as swap. Unlike zswap (which is a cache in front of disk swap), zram is the swap. There is no disk fallback unless you also configure a swap partition. It is the default on Android, ChromeOS, and is now the default on Fedora, Ubuntu 22.10+, and Arch's systemd-zram-generator.

Check Current zram Status

zramctl
swapon --show

Install the generator if not present:

# Fedora/RHEL:
sudo dnf install zram-generator

# Debian/Ubuntu:
sudo apt install systemd-zram-generator

# Arch:
sudo pacman -S zram-generator

Create or edit the configuration:

sudo nano /etc/systemd/zram-generator.conf

A typical configuration:

[zram0]
# Size: half of physical RAM, up to 8 GB
zram-size = min(ram / 2, 8192)
compression-algorithm = zstd
swap-priority = 100

Apply without rebooting:

sudo systemctl daemon-reload
sudo systemctl start /dev/zram0
swapon --show

Manual zram Setup (No Generator)

sudo modprobe zram
echo lz4 | sudo tee /sys/block/zram0/comp_algorithm
# Set size to 4 GB:
echo $((4 * 1024 * 1024 * 1024)) | sudo tee /sys/block/zram0/disksize
sudo mkswap /dev/zram0
sudo swapon -p 100 /dev/zram0

Note: zswap and zram together make little sense — you would be double-compressing. Disable zswap if you are using zram as your only swap backend:

echo 0 | sudo tee /sys/module/zswap/parameters/enabled

Verification

# Overall memory and swap picture:
free -h

# Confirm swap type and priority:
swapon --show

# Live compression stats for zram:
zramctl

# zswap hit/miss rates (if using zswap):
grep -r . /sys/kernel/debug/zswap/

# Current sysctl values:
sysctl vm.swappiness vm.vfs_cache_pressure

Troubleshooting

zswap Not Appearing in /sys/kernel/debug/zswap/

The debug FS may not be mounted. Run sudo mount -t debugfs none /sys/kernel/debug and retry. Add it to /etc/fstab if needed.

zram Device Busy on Resize

zram parameters cannot be changed while the device is active. Run sudo swapoff /dev/zram0, make changes, then re-enable. With the generator, edit the config and run systemctl restart [email protected].

High CPU Usage After Enabling Compression

Switch from zstd to lz4 for lower latency at the cost of compression ratio. On modern CPUs with many idle cores, zstd is usually fine; on embedded or single-core systems, lz4 or lzo is preferable.

Swap Still Going to Disk Despite zswap

zswap fills its pool and spills to disk swap when the pool hits max_pool_percent. Increase the pool or reduce total memory pressure. Check zswap.pool_total_size vs zswap.stored_pages in debugfs to see how full the pool is.

tested on:Ubuntu 24.04Fedora 40Arch 2024.06Debian 12

Frequently asked questions

Does setting vm.swappiness=0 disable swap entirely?
No. A value of 0 makes the kernel extremely reluctant to reclaim anonymous pages but it will still swap under genuine memory pressure. To truly disable swap, run swapoff -a.
Can I run both zswap and zram at the same time?
Technically yes, but it is wasteful. zswap would compress pages before sending them to the zram device, which compresses them again. Choose one: zswap if you have a disk swap backing store, zram if you want a pure in-RAM compressed swap target.
How much RAM should I allocate to zram?
A common starting point is half of physical RAM with a ceiling of 8 GB, as expressed by min(ram/2, 8192) in the generator config. With a 3:1 average compression ratio, this effectively provides up to 24 GB of swap space from 8 GB of RAM.
Which compression algorithm should I pick for zswap or zram?
lz4 has the lowest CPU overhead and is best for latency-sensitive workloads or slow CPUs. zstd achieves significantly higher compression ratios (useful when RAM is severely limited) at moderate CPU cost. lzo-rle is a reasonable middle ground on older kernels.
Why does the kernel still evict file cache even with low swappiness?
vm.swappiness biases the balance but doesn't prevent file-cache eviction. Under heavy memory pressure the kernel reclaims whatever is cheapest. Dirty file pages must be written back before eviction, so clean file cache often gets dropped first regardless of swappiness.

Related guides