Swap is not extra memory. It is a bet: the kernel picks pages it predicts will not be needed soon, writes them to a device, and frees the RAM. When the prediction holds, a spike passes without killing a process. When it does not, every wrong guess costs a device round trip, three to five orders of magnitude above reading RAM.

The trade only works as a valve. Sizing swap to cover a chronically under-provisioned workload buys a machine that is slow in a way that looks like a CPU problem; the first question is how much of the working set does not fit.

Reclaim picks victims by prediction

Anonymous pages, the heap, the stack and anything malloc handed out, have no file behind them, so they are the only thing swap holds. File-backed pages do not need swap: the kernel can drop a clean page-cache entry and read it back later. vm.swappiness is documented as the rough relative IO cost of swapping versus filesystem paging, on a scale from 0 to 200 with a default of 60. At 0 the kernel will not initiate swap until free plus file-backed pages fall below the zone’s high watermark, so 0 means “only under duress”, not “no swap”.

Internally the dial becomes a scan weight: swappiness for the anonymous list, 200 - swappiness for the file list. Values above 100 are not a mistake: the documentation suggests 133 when random IO against the swap device is about twice as fast as filesystem IO, and recommends beyond-100 values for in-memory swap such as zram or zswap.

The price is a device round trip

Latencies tell the story: roughly 100 ns for a resident DRAM page, single-digit microseconds for compressed swap in RAM, 100 us on NVMe, 250 us on SATA SSD, 8 ms on a spinning disk. A swap-in is a thousand times a RAM hit on NVMe and eighty thousand times on a disk, and the bill is charged per page needed again.

Model 100,000 page-sized accesses per second over an 8 GiB working set: fitting in RAM, the average is 100 ns with no major faults; at 2% over, 2.1 us, twenty-one times worse; at 20% over, 16.8 us, 167 times worse, with 16,667 major faults per second and 67 MB/s through si and so. The cliff begins at the first page that does not fit.

Thrashing is a device saturation problem

The same 20% overcommit is unremarkable on compressed swap, absorbable on NVMe, and fatal on a spinning disk. A 7,200 rpm disk serves on the order of 150 random IOPS, so 16,667 faults/s cannot be met; the shortfall is never served and the wait queue grows until the OOM killer. This is thrashing: a queueing failure, not a slow-memory failure.

zram and zswap change the cost model, not the principle. zram serves a fault from compressed RAM in microseconds instead of a device round trip, which is why the documentation suggests swappiness above 100. It expects roughly a 2:1 compression ratio, so making a device larger than twice memory buys little. The two sit in different places: zram is the swap device itself, with compressed pages staying in RAM; zswap is a compressed cache in front of a real swap device, evicting to it on an LRU basis when its pool hits its size limit. zram moves swap into memory; zswap only defers the write. Both make /tmp a natural use case, where swap and temp directories stop being separate problems: both are RAM with a cap.

When it breaks

Thrashing presents as a machine busy and idle at once. The load average climbs while CPU utilisation stays low, si and so climb, and major faults dominate. Every process progresses at a fraction of its normal rate while the box is not CPU-bound, which is why this gets misdiagnosed as an application problem. Confirm with vmstat 1: sustained si/so in the thousands of KiB/s alongside a rising run queue and idle CPU is the signature.

The second failure is swap that was never attached. swapon(8) documents that the kernel writes to the swap file directly, without the filesystem’s help, so a file with holes is rejected; truncate and cp both produce one. The same page documents -e/--ifexists and nofail, which silently skip a device that is not there, so a host can boot with no swap, look healthy until the first spike, and OOM-kill something important. Read /proc/swaps rather than trusting /etc/fstab.

Check it quickly

swapon --show
free -h
vmstat 1 5
grep -E 'pswpin|pswpout|pgmajfault' /proc/vmstat

swapon --show should list a device with a nonzero size; empty output means nothing is attached. In vmstat, si and so should sit near zero; sustained thousands of KiB/s with us plus sy low is thrashing rather than load. A climbing pgmajfault means pages are coming back from the device; a flat counter means the working set is resident.

Sources

  • swapon(8), swap priority, discard policies, and why a sparse swap file is rejected, checked 2026-09-16.
  • Kernel sysctl vm documentation, swappiness as a 0-200 relative IO cost dial with the zram guidance, checked 2026-09-16.
  • Kernel zram documentation, compressed RAM block devices, the expected 2:1 ratio, and the /tmp use case, checked 2026-09-16.
  • Kernel zswap documentation, the compressed swap cache in front of a backing device and its LRU eviction, checked 2026-09-16.