memory pressure, one command per page
Twenty-eight lessons on memory pressure, one command or file per page: free's six columns, what buff/cache borrows and why available beats free; /proc/meminfo from MemAvailable's parts to Active against Inactive and Dirty against Writeback; ps sorted by RSS, what RSS leaves out, RSS against VSZ and the %MEM sum; vmstat's since-boot first line, the si and so swap columns, the cpu tail and bi and bo; swapon's table, SwapCached's saved IO, vm.swappiness on its 0 to 200 scale and sysctl under /proc/sys; slab in meminfo, slabtop's ranked caches, the dentry rows and drop_caches; and the OOM killer's oom_score, oom_score_adj and dmesg record, one real command per page.
One command, one file, one real number. That's a page.
memory pressure, one command per page
Twenty-eight lessons on memory pressure, one command or file per page: free's six columns, what buff/cache borrows and why available beats free; /proc/meminfo from MemAvailable's parts to Active against Inactive and Dirty against Writeback; ps sorted by RSS, what RSS leaves out, RSS against VSZ and the %MEM sum; vmstat's since-boot first line, the si and so swap columns, the cpu tail and bi and bo; swapon's table, SwapCached's saved IO, vm.swappiness on its 0 to 200 scale and sysctl under /proc/sys; slab in meminfo, slabtop's ranked caches, the dentry rows and drop_caches; and the OOM killer's oom_score, oom_score_adj and dmesg record, one real command per page.
Set in Space Grotesk, Inter and JetBrains Mono (SIL Open Font License).
Every fact in this book is as the official source states it, fetched and read during this build: the Linux man-pages man7.org pages for free(1), ps(1), vmstat(8), slabtop(1) and sysctl(8) from procps-ng, dmesg(1) and swapon(8) from util-linux, and proc(5); and the kernel's own Documentation admin-guide/sysctl/vm.rst (swappiness, overcommit_memory, drop_caches, oom_dump_tasks) and filesystems/proc.rst (meminfo, oom_score, oom_score_adj) from kernel.org. No facts are sourced from Reddit, Stack Overflow or vendor blogs. Every command and output pair on every page was run on this machine (procps-ng 4.0.4, util-linux 2.39.3) and confirmed before printing; the drop_caches and oom_score pages present the kernel's documented values as written, for you to run on a box you own. An independent guide, not affiliated with or endorsed by the Linux man-pages maintainers, the procps-ng or util-linux projects, or the Linux kernel developers.
Your purchase is for personal use only. You do not have redistribution rights: please do not share, resell, or republish this book or its pages.
© 2026 Steve Hodgkiss. All rights reserved. Personal use only; no redistribution rights.
Edition 1.0 · stevehodgkiss.net
Contents
Per Linux man-pages free(1) (procps-ng): free displays the total amount of free and used physical and swap memory in the system, as well as the buffers and caches used by the kernel; the information is gathered by parsing /proc/meminfo; total is total usable memory, used is calculated as total minus available, free is unused memory, shared is mostly tmpfs, buff/cache is the sum of buffers and cache, and available estimates memory for starting new applications without swapping.
free's six columns
One command, two rows. The Mem row is physical RAM, the Swap row is the overflow disk, and each names six columns: total, used, free, shared, buff/cache, available.
Our run: 7.8Gi total, 2.7Gi used, 4.2Gi free, 1.2Gi buff/cache, 5.0Gi available. Swap holds a rounding error, 512Ki of 2.0Gi.
Per free(1), every number here is parsed straight out of /proc/meminfo: this row is a view of that file.
Run free -h, write down your total, buff/cache and available values, and check that used plus free plus buff/cache lands near your total.
Per kernel Documentation filesystems/proc.rst: meminfo provides information about distribution and utilization of memory, varies by architecture and compile options, and some of the counters reported here overlap, so the memory reported by the non overlapping counters may not add up to the overall memory usage. Per Linux man-pages free(1): free gathers its information by parsing /proc/meminfo. This machine's file opens MemTotal: 8131768 kB and reaches Slab: 826244 kB within the first 25 lines.
cat /proc/meminfo
One file, every counter: MemTotal, MemFree, MemAvailable, Buffers, Cached and dozens more, one per line, all in kB.
Our head of the file opens MemTotal: 8131768 kB and closes its first screen at Slab: 826244 kB. free, vmstat and ps are all views onto this file.
The docs warn the counters overlap and do not have to add up: read each line as its own claim.
Run head -n 25 /proc/meminfo, find your MemTotal and MemAvailable lines, and note the kB unit on every line.
Per Linux man-pages ps(1): --sort spec sets the sorting order with the syntax plus or minus followed by a key chosen from the standard format specifiers, and rss is resident set size; the u format displays user-oriented columns including user, pid, pcpu, pmem, vsz, rss and args. This machine's ps aux --sort=-rss run ranks a python3 process first at RSS 943708 kB, a dashboard python second at 930232 and a cron worker third at 344264.
ps sorted by RSS
One command ranks the eaters: ps aux --sort=-rss. The minus means descending, and the key is rss, resident set size.
Our podium: python3 at 943708 kB, the dashboard python at 930232, a cron worker at 344264. Two interpreters own most of this box's memory.
Sort by RSS, not VSZ, when the question is who is holding physical memory right now.
Run ps aux --sort=-rss, write down your top three RSS values with their commands, and note what share of your MemTotal they hold.
Per Linux man-pages vmstat(8): si is the amount of memory swapped in from disk per second and so is the amount of memory swapped to disk per second; swpd is the amount of swap memory used, free is idle memory, buff is buffers and cache is cache. In this machine's vmstat 1 5 run every row reports si 0 and so 0 with swpd steady at 512.
The si and so columns
Two columns watch the door to swap: si, memory swapped in from disk each second, and so, memory swapped out.
Our five rows read si 0, so 0 with swpd steady at 512 KiB: nothing moving. The 512Ki free(1) reported is residue, not traffic.
si and so above zero for rows on end is thrashing's heartbeat; zeros mean swap exists but is not being consulted.
Run vmstat 1 5, read the si and so columns across all five rows, and say whether your swap door is moving.
Per kernel Documentation admin-guide/sysctl/vm.rst: swappiness defines the rough relative IO cost of swapping and filesystem paging, as a value between 0 and 200; at 100 the VM assumes equal IO cost and will apply memory pressure to the page cache and swap-backed pages equally; lower values signify more expensive swap IO; the default value is 60; at 0 the kernel will not initiate swap until the amount of free and file-backed pages is less than the high watermark in a zone. This machine reports 60, read from /proc/sys/vm/swappiness.
vm.swappiness
swappiness prices the two escapes from pressure. At 100 the kernel treats swap and page cache as equally costly; lower says swap IO is dearer; above 100 says swap is cheaper than the filesystem.
Our value: 60, read straight from /proc/sys/vm/swappiness, and it is the documented default.
At 0 the kernel will not initiate swap until free and file-backed pages fall below a zone's high watermark.
Run cat /proc/sys/vm/swappiness, place your value on the 0 to 200 scale, and say which side of equal cost it votes for.
Per Linux man-pages slabtop(1): slabtop displays detailed kernel slab cache information in real time, a listing of the top caches sorted by one of the listed sort criteria, with a statistics header filled with slab layer information; -o displays the output once and then exits; the default sort criteria is the number of objects; the information comes from /proc/slabinfo. This machine's slabtop -o run reports Active / Total Objects 2469715 / 2539100, 97.3 percent.
slabtop -o
slabtop -o prints once and exits: the header totals, then the top caches ranked by object count.
Our header: 2469715 active of 2539100 objects, 97.3% in use; nearly every allocated slab object is alive.
The same numbers live in /proc/slabinfo; slabtop is that file, ranked and toted.
Run slabtop -o, write down your Active / Total Objects line, and find which cache holds the most objects on your list.
Per kernel Documentation filesystems/proc.rst, chapter 3: /proc/pid/oom_score displays the current score used by the oom-killer for any given task; the badness heuristic assigns each candidate task a value ranging from 0, never kill, to 1000, always kill, roughly a proportion of the allowed memory the process may allocate from based on an estimate of its current memory and swap use; a task using all allowed memory scores 1000, one using half scores 500; the exported value includes oom_score_adj so it is effectively in range 0 to 2000.
oom_score
Every task carries a kill ranking. The badness heuristic scores 0, never kill, to 1000, always kill: roughly the share of its allowed memory a process is using.
Using everything scores 1000; using half scores 500. /proc/pid/oom_score shows the number, and it includes oom_score_adj, so it can reach 2000.
Read oom_score before the kernel enforces it: the ranking is public, per process, all the time.
Run cat /proc/self/oom_score, then read the same file for your biggest process from ps aux --sort=-rss, and compare the two rankings.