NOTE 005intermediate14 min read

Linux memory beyond used versus free

Read RAM as anonymous memory, reclaimable cache, kernel state, swap, and pressure—then separate host capacity from cgroup limits.

FIG. 05 / INTERACTIVE MODEL

Used memory is not one kind of memory

Move through a workload. Watch reclaimable cache, anonymous pages, swap, and local cgroup pressure diverge.

Physical RAM / 100 illustrative units

Anonymous25Page cache25Kernel10Free40cgroup max
Swap occupancy
0 units
Host pressureLow

Plenty of MemAvailable; no meaningful stalls.

Cgroup pressureLow

No local limit is constraining this workload.

  1. 0Idle headroom
  2. 1File read
  3. 2Process allocation
  4. 3Reclaim + swap
  5. 4Cgroup limit

Text equivalent

Anonymous pages hold process-private data. File-backed page cache can often be reclaimed and re-read. “Available” estimates usable headroom better than “free” alone. Swap can preserve cold anonymous pages, while a cgroup can experience local reclaim or OOM even when the host has headroom.

Figure note

Categories are deliberately simplified and not additive to every/proc/meminfo counter. Shared pages, slabs, huge pages, tmpfs, zswap, and accounting overlap require workload-specific inspection.

A Linux host with little free memory may be healthy. A container on that host may be near its own limit. A process with a huge virtual address space may touch very little physical RAM. “Used versus free” collapses three different questions: what occupies memory, what can be reclaimed, and whether work is stalling.

Model boundary: The figure uses broad categories with illustrative percentages. Real kernel accounting overlaps in places, evolves across kernel versions, and cannot always be summed naively. Use the model to choose evidence, then interpret fields using documentation for the running kernel.

Start with availability, not emptiness

/proc/meminfo exposes system-wide memory counters. free derives its display from those counters 1 2.

free -h
sed -n '/^MemTotal:/p; /^MemFree:/p; /^MemAvailable:/p; /^Buffers:/p; /^Cached:/p; /^SReclaimable:/p; /^Swap/p' /proc/meminfo

Three labels answer different questions:

  • MemFree is RAM not currently used for anything.
  • Cached, Buffers, and reclaimable slab include memory serving useful cache and kernel work; their accounting is not one interchangeable bucket.
  • MemAvailable estimates how much memory can be made available for starting new applications without swapping, considering reclaimable memory and watermarks 1.

The kernel can use otherwise idle RAM to cache file data and metadata. That can reduce storage I/O. Calling all cache “wasted” reverses its purpose; the question is whether enough of it is reclaimable quickly when demand changes.

Four useful physical-memory categories

The interactive bar groups memory into:

  1. Anonymous memory — process heaps, stacks, and private mappings without a file providing their current contents.
  2. Page cache — cached file-backed pages, some of which may be clean and readily reclaimable while dirty pages need writeback.
  3. Kernel memory — slab objects, page tables, networking buffers, and other kernel-managed state, with differing reclaimability.
  4. Immediately free memory — pages currently on free lists.

This grouping is intentionally not a formula for recreating free. Counters can overlap or describe subcategories. Use it to ask “what kind grew?” before asking “how do I empty it?”

Virtual size is not resident size

A process address space can include executable mappings, shared libraries, reserved-but-untouched regions, file mappings, anonymous pages, and shared pages.

ps -eo pid,comm,vsz,rss --sort=-rss | sed -n '1,12p'
  • VSZ/VmSize describes virtual address space. Reservation alone does not mean the same amount of physical RAM is resident.
  • RSS/VmRSS estimates pages currently resident for that process.
  • Shared resident pages can appear in the RSS of multiple processes, so adding RSS across processes can double-count physical pages.
  • PSS divides shared pages proportionally and is available through smaps interfaces when permissions allow 4.

Inspect one known PID:

pid=$$
sed -n '/^Name:/p; /^VmSize:/p; /^VmRSS:/p; /^RssAnon:/p; /^RssFile:/p; /^RssShmem:/p; /^Threads:/p' "/proc/$pid/status"
sed -n '/^Rss:/p; /^Pss:/p; /^Anonymous:/p; /^Swap:/p' "/proc/$pid/smaps_rollup" 2>/dev/null

/proc/PID/status is convenient but some values are documented as inaccurate for precise accounting 3. smaps_rollup is more detailed and more expensive to gather; access may be restricted. Sample deliberately rather than scraping every process continuously.

A file read can make “free” fall healthily

Consider a large file read:

before: free pages available
read:   storage supplies file pages
after:  clean file pages remain cached
demand: kernel can reclaim suitable cache pages for another allocation

The workload got faster on a repeated read while MemFree fell. Under new demand, reclaim may shrink that cache. If writeback, reclaim, or refaults become intense, latency can rise; category names alone do not describe that experience.

There is rarely a good diagnostic reason to force-drop caches on a live system. Doing so destroys useful state and can manufacture an I/O spike without fixing the workload that created pressure.

Swap is a mechanism, not a verdict

Swap can hold anonymous pages that the kernel chooses to move out of RAM. That may preserve file cache or make room for a more active working set; it can also introduce severe latency when pages are repeatedly needed.

free -h
vmstat 1 5
cat /proc/pressure/memory 2>/dev/null

In vmstat, sustained si/so activity supplies more context than a non-zero swap-used total. Pages can remain in swap even after pressure subsides, so “swap is used” does not prove the machine is currently thrashing. Conversely, a system without swap can still suffer reclaim stalls and OOM events.

Pressure Stall Information (PSI) reports time in which tasks stall because a resource is contended; memory some and full signals help distinguish occupied RAM from workload-visible pressure 6.

The host and a cgroup have separate boundaries

Control group v2 can account and constrain a workload below host capacity. The memory controller exposes files such as:

for item in memory.current memory.min memory.low memory.high memory.max memory.events memory.pressure; do
  path="/sys/fs/cgroup/$item"
  if test -r "$path"; then
    printf '\n[%s]\n' "$item"
    sed -n '1,12p' "$path"
  fi
done

The root shown here is appropriate only when the observed workload belongs to that cgroup. A service or container normally has a deeper cgroup path. Locate it from the workload’s /proc/PID/cgroup, then inspect the corresponding authorized directory.

Important v2 signals include 5:

  • memory.current: accounted usage for the cgroup and descendants.
  • memory.high: a throttling/reclaim boundary; exceeding it can hurt latency.
  • memory.max: a hard limit that can lead to an OOM event if usage cannot be reduced.
  • memory.events: counters such as high, max, oom, and oom_kill.
  • memory.pressure: PSI scoped to that cgroup.

The host can show high MemAvailable and low global PSI while one container is reclaiming heavily at memory.high or hitting memory.max. Always pair host and workload scope.

OOM is an event with policy

When an allocation cannot be satisfied, Linux may invoke out-of-memory handling. That can happen at a system scope or within a constrained memory cgroup. The kernel selects a response using context and policy; “the biggest process always dies” is not a reliable model 7.

Read evidence before restarting away the scene:

journalctl -k --since '1 hour ago' 2>/dev/null | grep -Ei 'out of memory|oom|killed process'
cat /sys/fs/cgroup/memory.events 2>/dev/null

Kernel logs may require privileges and a systemd journal may not exist. Cgroup event counters can show that a local OOM occurred even when the host never ran out of RAM.

Leak, cache, or working set?

One snapshot cannot distinguish them. Trend the same scope under comparable load, and relate growth to activity and pressure.

Pattern Evidence to seek
Possible leak Anonymous/PSS trend does not return after work ends; object or allocation counts rise
File-cache growth File-backed/cache fields rise after I/O and can reclaim without repeated refault pain
Legitimate working-set growth Memory follows active users/data and stabilizes at a new useful level
Kernel growth Slab or other kernel categories rise; identify reclaimable versus unreclaimable owners
Cgroup pressure Local current approaches high/max; local PSI and events rise despite host headroom

A practical observation set is:

scope + timestamp
MemAvailable and host memory PSI
workload RSS/PSS split and trend
cgroup current/high/max, local PSI, and event deltas
swap-in/swap-out rate
application throughput, latency, and workload level

Capacity is not just a colored bar. Healthy analysis connects accounting to reclaimability, scope, time, and whether real work is waiting.

Reference ledger

Primary sources

  1. Linux man-pages — proc_meminfo(5)
  2. procps-ng manual — free(1)
  3. Linux man-pages — proc_pid_status(5)
  4. Linux man-pages — proc_pid_smaps(5)
  5. Linux kernel documentation — Control Group v2 memory controller
  6. Linux kernel documentation — PSI pressure stall information
  7. Linux kernel documentation — Out of Memory Handling