Part 2 · 2 chapters · ~12 min
Virtual Memory and Paging
Address translation with pages and page tables, the TLB and huge pages, page faults minor and major (measured), demand paging, copy-on-write and fork, memory-mapped files, swapping and the OOM killer, overcommit, and what RSS, VSZ and the page cache actually mean.
5
Translation and faults
code
// measured on this machine: touching 256 MB of fresh memory const b = Buffer.alloc(256 * 1024 * 1024); for (let i = 0; i < b.length; i += 16384) b[i] = 1; // process.resourceUsage().minorPageFault grew by 16,590 ≈ 256 MB ÷ 16 KB pages (16,384) + runtime noise
VIRTUAL TO PHYSICAL
every memory access goes through translation, cached in the TLB
swipe the figure sideways, or tap expand for full screen
1/5
pages
Memory is managed in pages: 4 KB on most x86 systems, 16 KB on this Mac (hw.pagesize = 16384). A virtual address is a page number plus an offset within the page.
page number + offset16 KB pages on Apple Silicon
6
Copy-on-write, mmap, swapping and the OOM killer
| mechanism | what happens | where it matters |
|---|---|---|
| demand paging | memory is mapped lazily on first touch | VSZ (virtual size) is huge; RSS (resident) is what is used |
| copy-on-write | after fork, parent and child share pages until one writes | cheap fork; Redis snapshots (BGSAVE) rely on it, and memory grows with write rate during a save |
| memory-mapped files | file pages appear in the address space via the page cache | databases (LMDB, older MongoDB), fast file reads |
| overcommit | Linux allows allocating more than RAM, betting not all is touched | when the bet loses, the OOM killer picks a process to kill |
| swapping | cold pages moved to disk | servers usually avoid swap: latency collapses |
| huge pages | 2 MB / 1 GB pages, fewer TLB misses | databases and JVMs with large heaps (transparent huge pages can cause latency spikes) |