Notes

Interpreting Linux Memory Metrics

May 25, 2026

note

Linux memory accounting is full of metrics that look similar but measure very different things. This post is a short tour of the most useful ones and where they come from.

How Linux Models Memory

Linux gives every process a private virtual address space. Pages in that space may or may not be backed by physical RAM at any given moment - the kernel pages them in on demand and evicts them under pressure. Many pages are also shared between processes (libraries, the page cache, copy-on-write forks), so “how much memory does this process use?” does not have a single right answer. It depends on whether you count what is reserved, what is resident, what is private, and how shared pages are split across processes.

On top of that, the kernel itself uses memory for the page cache, slab allocators, buffers, and reclaimable structures. “Free” memory is rarely the number you actually care about, because the kernel will happily use almost all RAM for cache and return it on demand.

Per-Process Metrics

From /proc/<pid>:

  • VSZ (Virtual Size): Total size of the process’s virtual address space, including code, data, mapped files, and unallocated reservations. Pages that are mapped but never touched still count. Useful as an upper bound, not as a usage number.
  • RSS (Resident Set Size): Amount of physical RAM currently backing the process’s pages. Shared pages are counted in full for every process that maps them, so summing RSS across processes overcounts system memory.
  • PSS (Proportional Set Size): Like RSS, but each shared page is divided by the number of processes sharing it. Summing PSS across all processes approximates total physical memory in use.
  • USS (Unique Set Size): Private resident memory only - the portion that would actually be freed if the process exited. The truest measure of a process’s incremental cost.
  • WSS (Working Set Size): The set of pages a process actively touches over a given time window. This is the minimum RAM the process needs to run without thrashing. Not a static counter; tools like wss.pl sample idle/young page flags to estimate it.
  • Swap: Pages that have been pushed out to a swap device. Visible per-process in /proc/<pid>/status (VmSwap) and smaps.

System-Wide Metrics

From /proc/meminfo:

  • MemTotal / MemFree: Total RAM and the small slice that is completely unused. MemFree is almost always misleadingly low on a healthy system.
  • MemAvailable: Kernel’s estimate of how much memory is available for new allocations without swapping, accounting for reclaimable cache and slab. This is the field to watch.
  • Buffers / Cached: Page cache used for block devices and file contents. Reclaimable on demand.
  • SwapTotal / SwapFree: Swap device capacity and remaining space.
  • Dirty / Writeback: Pages modified in cache that still need to be flushed to disk. Spikes here can stall writes.

Pressure and Reclaim

Raw “used vs free” numbers do not tell you whether the system is struggling. Two further signals do:

  • PSI (Pressure Stall Information): Exposed at /proc/pressure/memory and per-cgroup at memory.pressure since kernel 4.20. Reports the percentage of wall time over 10s/60s/300s windows during which some tasks (some) or all tasks (full) were stalled waiting on memory reclaim. Even small non-zero values indicate the system is doing real work to find memory.
  • pgscan / pgsteal / pgmajfault in /proc/vmstat: Counters for how aggressively the kernel is scanning the LRU lists, reclaiming pages, and servicing major faults from disk. Rising rates here usually precede visible slowdowns.
  • pswpin / pswpout in /proc/vmstat: Pages swapped in from and out to disk. Non-zero pswpin means the system is paying real disk I/O to bring previously-evicted pages back into RAM - a direct indicator that the working set no longer fits.

When to Use Which

  • Capacity planning for a single process: USS for incremental cost, WSS for the RAM it actually needs to run without thrashing.
  • Adding up processes to explain total RAM: PSS. RSS double-counts shared libraries; USS undercounts them.
  • Sizing a container or cgroup memory limit: WSS plus headroom for the page cache the workload depends on. Setting the limit at RSS is a common cause of surprise OOM kills.
  • “Is the box about to OOM?": MemAvailable trending down plus PSI memory.full above zero. MemFree alone will mislead you.
  • Investigating a slowdown that “has plenty of free memory": PSI, pgscan, pgmajfault, and Dirty/Writeback. High scan rates with low fault rates mean the kernel is working to keep up; high major-fault rates mean it is losing.
  • Diagnosing a memory leak in a long-running process: watch RSS and USS over time. Rising USS is a real leak; rising RSS with flat USS is usually shared-library or cache growth.
  • Comparing two processes that load the same big library: USS, since RSS will charge each one the full library cost.
  • Deciding whether to add swap: SwapFree trending toward zero combined with non-trivial PSI memory.some means the system is already paging under pressure.
  • Tuning a database or file server: Cached and Buffers should be large - that is the page cache doing its job. Worry when Dirty spikes or Writeback stays elevated.
  • Choosing what to alert on in production: MemAvailable, PSI memory.full avg60, and swap-in rate (pswpin in vmstat). These three together catch nearly every memory-related incident before users do.

Further Reading