Bitdoze Logo

How to Identify Processes Using Swap Space in Linux

Find which processes use swap space in Linux with smem, /proc/VmSwap, and shell scripts. Covers swappiness tuning, swap troubleshooting, and container swap tracking.

DragosDragos22 min read
How to Identify Processes Using Swap Space in Linux

When a Linux server starts swapping, performance tanks. The problem: standard tools like docker stats and even top don’t always show you the real swap picture. You need to know which processes are actually consuming swap space so you can fix the root cause, not just throw RAM at it.

This guide covers three reliable approaches: smem (the tool I reach for first), reading /proc directly (no dependencies needed), and vmstat for detecting active swap thrashing. You’ll also get practical coverage of swappiness tuning, container swap tracking with cgroups v2, and modern compressed swap with zswap/zram. All of it applies to any Linux distro: Ubuntu, Debian, RHEL, Fedora, and the rest.

If you need a broader refresher on Linux administration, start with these essential Linux commands.

Quick diagnostic: 30-second swap health check

Before diving into per-process details, run these three commands to gauge whether you even have a problem.

Run these first

If swap is under 20% and vmstat shows si/so near zero, you’re fine. The rest of this guide is optional reading.

  • free -h: Shows total/used/available swap at a glance
  • smem -s swap -r -k | head: Top swap-consuming processes (install smem first if needed)
  • vmstat 1 5: Shows if swap is actively being read/written (si/so columns)
# 1. System-wide memory overview
free -h

# 2. Top 10 swap consumers
smem -s swap -r -k | head -10

# 3. Is swap actively being used? (5 samples, 1s interval)
vmstat 1 5

What “healthy” looks like:

  • free -h: Swap used under 20% of total, “available” column still has headroom
  • smem: Most processes show 0 kB swap, top consumer under 50 MB
  • vmstat: si and so columns at 0 or near-zero

What “concerning” looks like:

  • free -h: Swap used climbing past 50%, “available” under 1 GB
  • vmstat: si/so consistently in the hundreds of KB/s, the system is actively thrashing

For more on monitoring system resources on Linux, including alerting when swap usage spikes.

Understanding Linux swap space

Swap space acts as overflow for physical RAM. When the kernel runs low on memory, it moves less-frequently-used pages to swap, a partition or file on disk. This prevents the OOM killer from firing immediately, but at a cost: disk I/O is orders of magnitude slower than RAM.

Without any swap, hitting the memory ceiling means the OOM killer starts terminating processes. With swap, the system degrades gradually instead of crashing, but excessive swapping (“thrashing”) can make the system feel frozen.

Swap partition vs swap file

Swap Partition Swap File
Setup Dedicated partition on disk Regular file in a filesystem
Performance Slightly better on spinning disks (avoids filesystem overhead) On SSDs, the difference is negligible
Flexibility Fixed size, requires repartitioning to resize Easy to create, resize, or remove
Caveats N/A btrfs has restrictions on swap files (must be on a non-compressed, non-COW subvolume)

On a typical VPS or home server with SSDs, swap files are the pragmatic default. No partitioning needed, and you can set up shared storage on Linux alongside swap without worrying about partition layout.

How much swap should you allocate?

System RAM Recommended Swap Notes
2 GB or less 2x RAM Desktops, small VPS
2-8 GB Equal to RAM General-purpose servers
8-64 GB 0.5x RAM High-memory servers
64 GB+ Minimum 4 GB Large production servers

These are rough guidelines. Modern RHEL documentation says swap sizing depends on workload and whether you use hibernation, not just RAM size.

VPS swap defaults

Most cloud providers ship VPS instances with zero swap. For a server running Docker containers or databases, a 1-2 GB swap file is a cheap safety net. If you’re setting up a home server, the same logic applies. A small swap file prevents OOM kills during memory spikes.

Check per-process swap usage with smem

smem is the best tool for this job. It reads swap data from /proc but gives you sorting, filtering, per-user views, and human-readable output. It’s packaged in every major distro.

Installing smem

Verify the installation:

smem --version

Failure mode: If you get “command not found” after installing, your distro may not package it. Fallback: pip install smem (requires Python 3).

Top swap-consuming processes

smem -s swap -r -k

Flags: -s swap sort by swap column, -r reverse (descending), -k show units in KB/MB/GB.

Sample output:

  PID User     Command                         Swap      USS      PSS      RSS
 1315 root     /usr/bin/python litellm         60.1M    89.2M    91.4M    98.1M
1746  root     /usr/bin/python gunicorn       109.4M   112.3M   114.8M   120.2M
1588  root     node next-server (v14)          41.5M    52.1M    54.3M    60.8M
 780  root     /usr/bin/containerd             3.3M     18.7M    19.2M    25.4M
 875  root     /usr/bin/dockerd                6.4M     42.1M    43.8M    52.3M

The Swap column is what matters here. USS (Unique Set Size) and PSS (Proportional Set Size) show physical memory usage, useful context but separate from swap.

Filtering by process name

# Only postgres processes
smem -P postgres -s swap -r

# Per-user view (useful for multi-tenant servers)
smem -u -s swap -r

# Show percentages instead of absolute values
smem -s swap -r -p | head -20

These are practical for Docker/Dokploy hosts where you want to quickly check if a specific database or application is the swap hog.

Using /proc to find swap usage by process

When you can’t install smem (minimal containers, restricted environments), the /proc filesystem has everything you need. This is what smem reads under the hood.

Reading VmSwap from /proc/PID/status

The kernel tracks per-process swap in /proc/<PID>/status as the VmSwap field:

# Check swap for a specific PID
grep VmSwap /proc/1438/status
VmSwap:      512 kB

One-liner to list all processes with non-zero swap:

for f in /proc/[0-9]*/status; do
    awk '/^Name:/{n=$2} /^Pid:/{p=$2} /^VmSwap:/{if($2>0) print p, $2, n}' "$f" 2>/dev/null
done | sort -k2 -nr | head -20 | column -t

Failure mode: “No such file or directory” errors are normal. A process can exit between the moment you start iterating and the moment you read its /proc entry. Ignore them.

The smaps_rollup method (kernel 4.14+)

For an efficient aggregate of all memory mappings, smaps_rollup is faster than reading the full smaps file (which can be thousands of lines per process):

# All processes with non-zero swap, sorted descending
grep -H 'Swap:' /proc/*/smaps_rollup 2>/dev/null | awk -F'[: ]' '{print $1, $4}' | sort -t: -k2 -nr | head -20

/proc/*/smaps_rollup has been available since kernel 4.14 (2017). Every currently supported distro has it.

# Verify your kernel version
uname -r

Note: Reading the full /proc/<PID>/smaps for every process is expensive. htop had performance issues with this (see htop issue #1712). Use smaps_rollup instead.

Clean awk script (no dependencies)

Save this as swap-users.sh for a reusable, readable script:

#!/bin/bash
# swap-users.sh - List processes using swap, sorted by usage
printf '%-10s %12s  %s\n' "PID" "Swap" "Command"
for s in /proc/[0-9]*/status; do
    awk '/^Name:/{n=$2} /^Pid:/{p=$2} /^VmSwap:/{if($2>0) printf "%-10s %10s kB  %s\n",p,$2,n}' "$s" 2>/dev/null
done | sort -k2 -n -r

Make it executable and run:

chmod +x swap-users.sh
./swap-users.sh

Output:

PID             Swap  Command
1746         112000 kB  gunicorn
1387          12416 kB  gunicorn
449142        17536 kB  node
1588          42496 kB  next-server
1315          61568 kB  litellm
812            9344 kB  unattended-upgr
875            6528 kB  dockerd
780            3328 kB  containerd

Verify: Output should be sorted by swap usage descending. Empty output means no processes are using swap (which is fine).

For a quick inline version without saving a file:

for f in /proc/[0-9]*/status; do
    awk '/^Name:/{n=$2}/^Pid:/{p=$2}/^VmSwap:/{if($2>0)print p,$2,n}' "$f" 2>/dev/null
done | sort -k2 -nr | head -20 | column -t

Other tools: top, htop, and vmstat

The original article mentioned top and htop as monitoring tools. There are important caveats.

top’s SWAP column: what it actually shows

top SWAP column trap

If your top shows processes using hundreds of MB of swap while free -h shows only a few MB total, you’re running the old procps top that computes SWAP = VIRT - RES. This is not real swap usage. It includes memory-mapped files, video memory, and other virtual memory. Upgrade to procps-ng (standard on Ubuntu 16.04+, RHEL 7+, Debian 9+) or use smem instead.

On modern distros, top from procps-ng (version 3.3.10+) reads VmSwap from /proc correctly. Check your version:

top -v

If it shows procps-ng and a version ≥3.3.10, the SWAP column is accurate. If it shows just procps (no -ng), treat the SWAP column as fiction.

Source: Red Hat KB 237633, htop FAQ

Why htop doesn’t have a SWAP column

htop deliberately omits a per-process swap column. The reason: shared memory pages make per-process swap accounting unreliable. A shared library page can be “charged” to multiple processes, inflating the numbers. The htop developers decided it was better to show no swap column than a misleading one.

Use smem or the /proc methods above for per-process swap data.

Detecting swap thrashing with vmstat

vmstat shows real-time swap activity. The si (swap in) and so (swap out) columns are the key indicators:

vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  0 294000 678528  12032 5712832    0    0     2    15   89   12  3  1 96  0  0
 0  0 294000 678528  12032 5712832    0    0     0     0  102   15  2  1 97  0  0
 0  0 294000 678528  12032 5712832    0    0     0     0   98   12  1  1 98  0  0

Interpreting si/so

  • si/so near zero: Normal. Swap space is allocated but not actively being read/written.
  • si/so in the hundreds of KB/s: Actively swapping. Investigate with smem.
  • si/so in the thousands of KB/s: Thrashing. The system is spending more time swapping than doing work. Take action immediately.

With sysstat installed, you can also use:

# Swap activity report (10 samples, 1s interval)
sar -S 1 10

# Page fault and paging rate
sar -B 1 10

If swap thrashing is impacting your server performance, consider benchmarking your cloud server to compare upgrade options.

Swap and Docker containers

If you run Docker or Dokploy, this section is critical. Standard container monitoring doesn’t show swap at all.

Why docker stats doesn’t show swap

docker stats shows a “MEM USAGE” column, but that’s RSS + page cache. It does not include swap. A container could be swapping heavily and docker stats would show nothing unusual.

This is a common blind spot for anyone monitoring server and Docker resources. The memory numbers in docker stats look fine while the system is actually thrashing because a container’s anonymous pages are piling up in swap.

For Docker management commands beyond memory monitoring.

Tracking container swap with cgroups v2

On systems with cgroups v2 (default on Ubuntu 22.04+, Fedora 31+, Debian 11+), you can read per-container swap usage directly:

# Check cgroups version (should show "cgroup2fs")
stat -fc %T /sys/fs/cgroup/

# Swap used by a specific container
cat /sys/fs/cgroup/system.slice/docker-<container-id>.scope/memory.swap.current

The value is in bytes. Convert to MB: divide by 1048576.

Loop through all containers:

for cg in /sys/fs/cgroup/system.slice/docker-*.scope; do
    name=$(basename "$cg")
    bytes=$(cat "$cg/memory.swap.current" 2>/dev/null)
    if [ -n "$bytes" ] && [ "$bytes" -gt 0 ]; then
        mb=$((bytes / 1048576))
        echo "$name: ${mb} MB"
    fi
done

Requires cgroups v2

This only works on cgroups v2. If stat -fc %T /sys/fs/cgroup/ returns tmpfs instead of cgroup2fs, you’re on cgroups v1. Enabling cgroups v2 requires kernel boot parameters. Check your distro documentation.

Also useful: if you’re reclaiming disk space from Docker, remember that swap files also consume disk space.

Tuning swap behavior with vm.swappiness

The existing swappiness guidance in most articles is oversimplified or outdated. Here’s what actually matters.

What swappiness actually controls

Swappiness is not “how aggressively the kernel swaps.” It controls the kernel’s weighting between reclaiming two types of memory pages:

  • File-backed pages (page cache) — reading them back from disk is fast (sequential I/O on the filesystem)
  • Anonymous pages (application memory) — reading them back requires swap I/O (random I/O)

A higher swappiness value tells the kernel to prefer evicting anonymous pages to swap. A lower value tells it to prefer dropping page cache.

On SSDs, the cost of reading swap is similar to reading page cache, so higher swappiness values (100) are reasonable. On spinning disks, swap reads are expensive random I/O, so lower values make more sense.

Source: Chris Down, In defence of swap

Swappiness 0-200: kernel 5.8+ changes

Since kernel 5.8 (August 2020), vm.swappiness accepts values 0-200, not just 0-100. Values above 100 bias more heavily toward swapping anonymous pages.

Critical distinction:

Value Behavior
0 Never swap anonymous pages unless the system is near OOM (special semantics since kernel 3.5, 2012)
1 Lowest “normal” value — avoids swap but doesn’t have the special-case behavior of 0
60 Default on most distros. Balanced for general use
100 Treats file and anonymous pages equally. Good default for SSD-based systems

Persistent configuration with sysctl.d

The old approach of appending to /etc/sysctl.conf works but is messy. The modern method uses drop-in files:

# Check current value
sysctl vm.swappiness

# Apply temporarily (resets on reboot)
sudo sysctl -w vm.swappiness=60

# Apply permanently with a drop-in file
echo 'vm.swappiness=60' | sudo tee /etc/sysctl.d/99-swap.conf
sudo sysctl --system

Verify the change took effect:

sysctl vm.swappiness

Failure mode: Value not persisting after reboot? Another file in /etc/sysctl.d/ might be overriding it. Check with:

sudo sysctl --system 2>&1 | grep swappiness

Modern swap technologies: zswap and zram

If you’re running Linux 5.x+, there are better options than raw disk swap alone.

zswap: compressed write-back cache

zswap sits between the kernel’s memory allocator and disk swap. When the kernel wants to swap a page out, zswap compresses it first. If the compressed page fits in a RAM cache, no disk I/O happens. When the cache fills up, the least-recently-used pages get written to disk swap automatically.

This is the “enable and forget” option for most servers. On a VPS with SSD-backed swap, zswap reduces disk swap writes significantly.

Enable zswap on SSD-based servers

Add zswap.enabled=1 to your kernel command line (via GRUB or bootloader config). It’s a free performance win — compressed pages stay in RAM when possible, and only hit disk when necessary.

Check if zswap is active:

dmesg | grep zswap
cat /sys/module/zswap/parameters/enabled

zram: compressed RAM block device

zram creates a compressed block device entirely in RAM and uses it as swap. No disk I/O at all. Everything stays in memory, just compressed. Fedora uses zram by default (paired with systemd-oomd).

The tradeoff: zram has a hard capacity limit (typically 50% of RAM) and can cause LRU inversion when used alongside disk swap. It’s best for memory-constrained systems like laptops and containers, not general-purpose servers.

For most VPS/Dokploy setups, zswap with disk swap is the better choice.

Swap troubleshooting and verification

How to verify swap is active

# List all active swap devices with priorities
cat /proc/swaps

# Human-readable version
swapon --show

# Quick check
free -h

If swapon --show returns nothing, you have no swap configured. For most cloud VPS instances, this is the default — you need to create a swap file manually.

When swap is normal vs. when it’s a problem

Normal

Swap used 10–20%, vmstat si/so near zero. The kernel is keeping cold pages in swap to free up RAM for active workloads. This is expected behavior and not a problem.

Problem

Swap growing steadily over time, vmstat si/so consistently in the hundreds of KB/s or higher. The system is thrashing — spending more time swapping pages than doing actual work. Add RAM, kill processes, or optimize memory-hungry applications.

The distinction: swap allocation (pages sitting in swap) is fine. Swap activity (pages being constantly moved between RAM and swap) is the problem. vmstat si/so columns tell you which one you have.

How to safely clear swap

To move all swap pages back to RAM:

sudo swapoff -a && sudo swapon -a

Check free RAM first

Before clearing swap, run free -h and confirm that available RAM is greater than swap used. If there’s not enough free RAM, swapoff will hang or trigger the OOM killer. Stop memory-heavy services first if needed.

Verify swap cleared:

free -h
# Swap used should drop to near zero

Using systemd-oomd to prevent swap storms

On Ubuntu 22.04+ and Fedora, systemd-oomd is enabled by default. It uses PSI (Pressure Stall Information) to detect when the system is under memory pressure and kills memory-hungry processes before swap fills up completely.

Check if it’s running:

systemctl status systemd-oomd

If it’s not active and you’re on Ubuntu 22.04+ or Fedora, enable it:

sudo systemctl enable --now systemd-oomd

For older distros, earlyoom is a simpler alternative available in most repos:

sudo apt install earlyoom    # Debian/Ubuntu
sudo dnf install earlyoom    # RHEL/Fedora
sudo systemctl enable --now earlyoom

Conclusion

Three things to remember about swap on Linux:

  1. Use smem as your go-to tool. smem -s swap -r -k gives you the clearest, most accurate per-process swap picture. Fall back to /proc scripts when you can’t install packages.

  2. vmstat si/so is the real danger signal. Swap allocation is normal. Swap activity (high si/so) means the system is thrashing and needs attention.

  3. Enable zswap on SSD-based servers. It’s a one-line kernel parameter that reduces disk swap writes for free.

If you’re consistently hitting swap limits, the fix is usually more RAM — not more tuning. For affordable VPS upgrades, Hetzner Cloud VPS starts at a few euros per month with SSD storage. Hostinger VPS and Vultr are solid alternatives with global datacenter coverage. DigitalOcean is another option if you want a developer-friendly platform.

For more Linux administration guides, check out our essential Linux commands reference and the guide to monitoring system resources on Linux with email alerts.