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:
MemFreeis 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.MemAvailableestimates 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:
- Anonymous memory — process heaps, stacks, and private mappings without a file providing their current contents.
- Page cache — cached file-backed pages, some of which may be clean and readily reclaimable while dirty pages need writeback.
- Kernel memory — slab objects, page tables, networking buffers, and other kernel-managed state, with differing reclaimability.
- 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
smapsinterfaces 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 ashigh,max,oom, andoom_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
- Linux man-pages — proc_meminfo(5)
- procps-ng manual — free(1)
- Linux man-pages — proc_pid_status(5)
- Linux man-pages — proc_pid_smaps(5)
- Linux kernel documentation — Control Group v2 memory controller
- Linux kernel documentation — PSI pressure stall information
- Linux kernel documentation — Out of Memory Handling