Behavioral Differences Between ZRAM and ZSWAP Under Memory-Constrained Scenarios

A machine with 8GB of physical memory while running IntelliJ IDEA, Docker, and Chromium simultaneously—memory pressure is the norm. The common fix is to set a ZRAM block device as the highest-priority swap device. This setup is indeed much faster than plain disk swap, but after a few days of uptime the machine still exhibits severe latency jitter: mouse stuttering, window switches taking seconds to respond.

The problem isn’t ZRAM itself—it’s that the reclamation policy and the storage backend are mismatched.

ZRAM vs ZSWAP: Fundamental Architectural Differences

Both perform memory compression, but they occupy entirely different positions in the stack.

ZRAM is a compressed block device. It registers as a /dev/zramX block device inside the kernel, whose storage backend consists of compressed pages in memory. Data flows in via swap_writepage(), traversing the standard block I/O path. ZRAM has no concept of cold vs. hot pages—it is merely a medium and does not participate in reclamation decisions. When the pool fills up, it falls back to the next swap device according to swap_info priority, with no policy whatsoever.

ZSWAP is a compressed cache layer. It sits inside the swap subsystem and intercepts pages early in the shrink_page_list() reclamation path. ZSWAP maintains metadata for compressed pages and works in concert with the kernel’s LRU machinery. It has a soft limit, max_pool_percent; when the pool is full, instead of blindly spilling over, it writebacks the coldest pages to the backing disk swap, freeing space for active data.

This architectural difference leads the two down entirely different paths under sustained high load.

LRU Inversion: Fast Media Filled With Garbage, Hot Data Stranded on Slow Disks

The expected behavior of Linux page reclamation is straightforward: evict Inactive (cold) pages first, protect Active (hot) pages.

But consider this setup:

  • /dev/zram0: priority 32767 (highest)
  • Disk swap: priority -1

During system startup, a large volume of one-shot initialization data is generated. These cold pages, when reclaimed, are the first to land in the highest-priority ZRAM. Once ZRAM is full, the core working set—IDEA’s and Docker’s hot pages—needs to be swapped out. ZRAM has no room left, so these pages are forcibly redirected to disk swap.

Cold data occupies high-speed ZRAM while hot data is stranded on slow disk—the LRU eviction intent is completely subverted by the swap priority configuration. This is LRU inversion, and kernel MM maintainers (such as Chris Down) explicitly oppose this kind of mixed configuration.

Writeback Strategy: Passive Rejection vs. Proactive Aging

Attribute ZRAM ZSWAP
Trigger mechanism Manual configuration or recent kernel support zswap_shrink() triggered automatically
Policy basis Based on pool exhaustion (policy-free) Based on LRU aging
MM integration Independent of the MM subsystem Deeply embedded in the reclaim path

ZSWAP can dynamically push the least recently accessed pages to disk, freeing pool space for currently active pages; ZRAM, once full, can only deny service.

I/O Path Overhead

ZRAM’s write path incurs the full block layer overhead:

Memory page → BIO allocation → Request queue → I/O scheduling → ZRAM driver → Compression

ZSWAP bypasses all of this:

Memory page → ZSWAP hook → Compression

That said, on desktop workloads ZSWAP’s real win lies less in a shorter I/O path and more in reducing the frequency of slow-disk I/O—LRU-aware eviction keeps the majority of swap-outs within the compressed cache layer, with only genuinely cold pages ever hitting the disk.

Constraints and Boundaries

Scenarios where both are limited:

  • HugeTLB pages: Not supported.
  • Tmpfs pages: Do not traverse the swap path; not managed.
  • Mlocked pages: Cannot be swapped out.

Key distinction: ZSWAP requires a disk swap as its backing store—it is fundamentally a cache layer; ZRAM can exist standalone, with no disk requirement.

How to Choose

For desktop or server environments with disk swap available, go with ZSWAP. Run as root:

swapoff /dev/zram0

echo 1 > /sys/module/zswap/parameters/enabled
echo zstd > /sys/module/zswap/parameters/compressor
echo 50 > /sys/module/zswap/parameters/max_pool_percent

A few takeaways:

  • ZRAM’s proper use case is diskless environments like embedded systems and Android—it was designed to “provide swap in the absence of a disk”;
  • On machines with disks, mixing ZRAM with disk swap creates the LRU inversion problem described above—ZRAM should be disabled;
  • ZSWAP paired with disk swap is currently the most stable memory-pressure solution for desktop Linux: treat compression as a cache, and let only truly cold data reach the disk.

ZRAM is a fine storage backend, but it has no reclamation intelligence; ZSWAP binds compression and eviction policy together. In an environment with disks, let each do what it’s built for—ZSWAP as a hot-data compressed cache, disk swap catching cold data—that’s the right direction.