Mac maintenance
How to Read vm_stat on Mac to Understand Memory Pressure
Make sense of vm_stat output on macOS — pages, swap, compression, and pageouts — to diagnose real memory pressure on Apple Silicon and Intel Macs.
Activity Monitor’s Memory tab gives you a “Memory Pressure” graph and a few summary numbers, but for diagnosing what’s actually happening with your Mac’s memory, the numbers behind that graph live in vm_stat. It’s a tiny command that prints a snapshot of the kernel’s memory state.
Reading it once is confusing. Reading it twice, with a gap, and learning what each line means, is one of those skills that pays off forever. Here’s the field-by-field walkthrough.
Run it
vm_stat
You’ll get something like:
Mach Virtual Memory Statistics: (page size of 16384 bytes)
Pages free: 123456.
Pages active: 789012.
Pages inactive: 345678.
Pages speculative: 12345.
Pages throttled: 0.
Pages wired down: 234567.
Pages purgeable: 56789.
"Translation faults": 98765432.
Pages copy-on-write: 345678.
Pages zero filled: 8765432.
Pages reactivated: 234567.
Pages purged: 45678.
File-backed pages: 456789.
Anonymous pages: 678901.
Pages stored in compressor: 123456.
Pages occupied by compressor: 45678.
Decompressions: 5678.
Compressions: 12345.
Pageins: 56789.
Pageouts: 1234.
Swapins: 123.
Swapouts: 45.
Note the page size at the top. On Apple Silicon Macs, pages are 16 KB (16384 bytes). On Intel Macs, pages are 4 KB (4096 bytes). To convert pages to bytes: pages × page size.
The big four
Most of what you care about is in four numbers:
Pages free — completely unused memory. This is misleadingly small on a healthy macOS — the OS uses every available byte for caches.
Pages active — memory that’s being actively used by running processes. The “real” memory consumption.
Pages inactive — memory that was used recently but isn’t right now. macOS keeps this around for fast re-access. It’s reclaimable instantly when something else needs the RAM.
Pages wired down — memory that cannot be paged out. Kernel data, drivers, in-flight DMA buffers. If this is huge, you have a kernel extension behaving badly.
A typical 16 GB Mac with a few apps open might show free=200K, active=400K, inactive=300K, wired=150K (in pages, with 16 KB pages). That’s about 3 GB free, 6 GB active, 5 GB inactive, 2 GB wired. 16 GB total, all accounted for.
The pressure indicators
The fields that signal real trouble:
Pageouts — pages written from RAM to disk. macOS only does this when it’s forced to. Non-zero is fine; rapidly growing is bad.
Swapouts — anonymous (non-file-backed) pages compressed or written out. Same idea, more specifically targeted.
Swapins — pages read back from swap. If this number is climbing fast, your system is constantly thrashing — pulling stuff back in that it just paged out.
Pages stored in compressor — pages that have been compressed in memory. macOS compresses inactive memory before it pages it to disk. If this is growing fast, the compressor is the only thing keeping you off swap.
A quick health check:
- Big number, slow growth on
Pageouts: fine. Background activity. - Big number, fast growth on
PageoutsandSwapins: real memory pressure. Things are being written and re-read. - Big number, fast growth on
Compressionsonly: compressor is doing its job. You’re under pressure but not yet swapping.
Compression on Apple Silicon
Apple Silicon Macs use the memory compressor aggressively. When inactive memory is pushed out, it’s compressed in-place rather than written to disk. The relevant fields:
Compressions— total compressions since boot.Decompressions— total times compressed pages had to be decompressed (i.e., read back).Pages stored in compressor— current count of compressed pages.Pages occupied by compressor— current physical pages used to hold the compressed data. This will be smaller than “stored” if compression’s working well — that’s literally the savings.
A healthy ratio: stored / occupied around 2.5–4x. So if you’re storing 1 GB of “logical” pages in 300 MB of physical pages, you’ve gotten 3.3x compression. That’s typical.
Watching the numbers change
The single snapshot is rarely useful. Add a number to make vm_stat poll:
vm_stat 2
That refreshes every 2 seconds, with deltas after the first row. You see how much things are changing in real time.
A pattern that signals a memory leak: Pages active slowly climbs without Pages inactive climbing to match. Something is allocating memory and never releasing it.
Converting pages to GB at a glance
Page size is 16384 bytes on Apple Silicon, 4096 on Intel. A handy one-liner to translate:
vm_stat | awk '
/page size of/ { ps=$8 }
/Pages free/ { printf "Free: %.2f GB\n", $3*ps/1073741824 }
/Pages active/ { printf "Active: %.2f GB\n", $3*ps/1073741824 }
/Pages inactive/{printf "Inactive: %.2f GB\n", $3*ps/1073741824 }
/Pages wired/ { printf "Wired: %.2f GB\n", $4*ps/1073741824 }
'
Drop that in ~/bin/memstat and you’ve got a one-shot summary in human units.
Checking swap
vm_stat shows pageouts and swapouts as cumulative counters. To see your current swap file size and usage:
sysctl vm.swapusage
Output looks like:
vm.swapusage: total = 4096.00M used = 1234.56M free = 2861.44M (encrypted)
total is how much swap macOS has allocated on disk. used is what’s currently filled. macOS encrypts swap by default — that’s the (encrypted) tag.
If used is consistently more than 2 GB on a personal machine, you have working-set problems. purge won’t fix this; closing tabs and apps might.
Memory pressure (the OS’s internal verdict)
macOS computes its own pressure level — green/yellow/red. To check from the Terminal:
memory_pressure
Returns either an interactive output or, with -l warn, a one-line verdict. The relevant section says:
The system has X percent of memory free.
The system has Y percent of memory available before paging.
This system is using a Compressed Memory Manager.
That number — “before paging” — is the most useful single metric for “should I worry.” Above 30%: comfortable. 10–30%: watch it. Below 10%: things are about to slow down.
Wired memory: when it’s a problem
Pages wired down is memory the kernel can’t page out. It’s used by:
- The kernel itself
- Network buffers
- Loaded kernel extensions
- File system metadata caches
- IO Kit driver allocations
On a healthy Mac with a clean install, wired memory is 1.5–3 GB. If yours is showing 6+ GB, something’s leaking in kernel space. Common culprits:
- Old third-party kernel extensions (Apple’s been deprecating these — most modern apps now use system extensions instead).
- VPN clients with badly-written kernel extensions.
- Virtualization tools.
- Some external drive drivers.
To list current kernel extensions:
kmutil showloaded
(kextstat was the old command; on recent macOS it’s kmutil.)
Translation faults and copy-on-write
Two fields that look alarming but usually aren’t:
Translation faults — every time the CPU walks the page table to find a virtual address. This number is huge (billions) on any Mac that’s been up for a while. It’s not an error count; it’s just normal CPU activity.
Pages copy-on-write — pages shared between processes (typically after fork()) that got copied because one of them wrote to it. Normal kernel behavior.
You can ignore both unless they’re growing wildly fast in the polling output.
File-backed vs anonymous
Two fields tell you how memory is being used:
File-backed pages — pages that mirror data on disk. App binaries, mapped files, dyld caches. These are essentially “free” from a pressure standpoint — the OS can drop them and re-read from disk if needed.
Anonymous pages — pages that don’t correspond to a file. Heap allocations, stacks. These are real, and have to go to swap if pushed out.
A Mac that’s mostly file-backed is healthy. A Mac that’s mostly anonymous is doing real work, and the upper bound on memory pressure is hard.
Comparing two snapshots
The most useful debugging trick: take a snapshot, do something, take another snapshot, diff:
vm_stat > /tmp/before.txt
# ... do the heavy thing ...
vm_stat > /tmp/after.txt
diff /tmp/before.txt /tmp/after.txt
You’ll see exactly which counters moved and by how much. If Pageouts went from 1234 to 9876 during a specific operation, that operation caused real swapping.
What “good” looks like
Some sanity benchmarks for a healthy Mac:
- Free + Inactive together = 30%+ of total RAM. (i.e., available memory.)
- Wired = 10–20% of total RAM.
- Pageouts grew by less than a few thousand per minute during normal work.
- Compression ratio (stored/occupied) is 2x or better.
sysctl vm.swapusageused = 0 or under a few hundred MB.
If you’re seeing all five of those, your Mac has plenty of memory for what you’re doing. If two or three of them are off, you’re at the edge of your hardware’s capability.
Common scripts
A simple one-second polling memory bar for the Terminal:
while true; do
vm_stat | awk '
/page size/ { ps=$8 }
/free/ { f=$3 }
/active/ { a=$3 }
/inactive/ { i=$3 }
/wired/ { w=$4 }
END {
printf "Free %.1fG Active %.1fG Inactive %.1fG Wired %.1fG\r",
f*ps/1073741824, a*ps/1073741824,
i*ps/1073741824, w*ps/1073741824
}'
sleep 1
done
Run it in a Terminal pane and watch the numbers update as you launch and quit apps. You’ll get a feel for what your Mac actually does with memory in normal use.
When to act on what you see
vm_stat is a diagnostic. When the numbers are bad, the fixes aren’t in the Terminal:
- Quit apps with large active footprints.
- Reboot if wired memory looks bloated.
- Uninstall kernel extensions you don’t need.
- Free disk space if swap can’t grow.
- Buy more RAM if your workload genuinely exceeds what you’ve got.
vm_stat won’t fix any of that. What it will do is tell you, in numbers, what’s going wrong — which is the half of the battle most people skip.