skip to content

A Java process on a 4 GB Linux machine shows a VSZ of 12 GB and an RSS of 800 MB in `ps` output. What does each of those two numbers measure, and why is the machine not out of memory?

level: middleimportance: should knowfreq 62%

answer

  1. reservation versus residency
  2. address space is nearly free
  3. first touch commits a page
  4. shared libraries counted in every process
  5. anonymous pages are the irreducible part

basics

~20 s

VSZ is the size of the process's virtual address space — mappings it may use, most of which are never backed by RAM. RSS is the pages actually resident in physical memory. Only RSS consumes RAM, so 12 GB of address space on a 4 GB box is unremarkable.

solid answer

~50 s

They measure two different things. **VSZ** (virtual size, `VmSize` in `/proc/<pid>/status`) is the total span of the process's address-space mappings: heap arenas it reserved, thread stacks, every shared library and file it mapped, plus guard regions. Reserving address space is nearly free on a 64-bit machine — it is bookkeeping in the page tables, not RAM. **RSS** (`VmRSS`) is the subset of those pages currently backed by physical memory, because the process touched them and the kernel faulted them in. A runtime that reserves a large heap or maps big files will always show a huge VSZ; that number cannot exhaust RAM. What you watch is RSS, and even RSS is imperfect: shared pages such as libc are counted in full in every process that maps them, so summing RSS across processes double-counts. When I need a fair per-process figure I read `Pss` from `/proc/<pid>/smaps_rollup`, which divides shared pages by the number of sharers.

code

bash · 3 lines
bash
pid=$$
grep -E '^(VmSize|VmRSS|RssAnon|RssFile|RssShmem):' /proc/$pid/status
grep -E '^(Rss|Pss):' /proc/$pid/smaps_rollup

go deeper

for a junior

Be ready to say that virtual size is address space a process reserved and resident size is what is really in RAM, and that only the second one competes for physical memory.

for a middle

Explain demand paging: an allocation creates a mapping, the first write faults, and only then does the kernel commit a physical page. Mention that shared library pages inflate resident size across processes.

for a senior

Show judgment about metrics: know that resident size double-counts sharing and hides swapped-out pages, reach for the proportional set size or the anonymous split, and reject limits keyed to address space.

for a principal

Own the standard your organisation measures against — which memory number goes on dashboards, in capacity models and in limit policy — and the cost of getting it wrong on a large fleet of runtimes that reserve address space aggressively.

## Two different accounting questions Every Linux process gets its own virtual address space: a private map from virtual addresses to backing storage, maintained by the kernel and enforced by the MMU. Two numbers describe it, and interviewers ask this because candidates routinely add them up as if they were the same currency. **Virtual size (VSZ / `VmSize`)** is the sum of the lengths of all mappings in the address space, whether or not anything is behind them. It grows when the process calls `mmap` or extends the heap with `brk`, and it includes: - the executable and every shared library mapped in, at their full on-disk size; - files the process mapped with `mmap` — a 10 GB mapped data file adds 10 GB of VSZ and zero RSS until pages are touched; - heap arenas: allocators such as glibc's malloc reserve large regions up front and hand out pieces of them; - one stack region per thread — a 1000-thread program with 8 MB stack reservations carries 8 GB of VSZ; - guard pages and other reservations with no memory behind them at all. **Resident set size (RSS / `VmRSS`)** counts the pages of that address space currently present in physical RAM. A page becomes resident when the process first touches it and the CPU raises a page fault that the kernel resolves — by allocating a zeroed page for anonymous memory, or by reading from the file for a file-backed mapping. This is **demand paging**: nothing is resident until it is used. ```bash grep -E '^(VmSize|VmRSS|RssAnon|RssFile|RssShmem):' /proc/self/status ``` ## Why VSZ can dwarf physical RAM A 64-bit process has an address space measured in terabytes. Reserving a slice of it costs a virtual-memory-area record in the kernel and nothing else. That is why 12 GB of VSZ on a 4 GB machine is not a contradiction: only the 800 MB that has been touched is occupying RAM. Managed runtimes make this dramatic — a JVM reserves its maximum heap as address space at startup and commits pages as the heap actually grows, so VSZ jumps immediately while RSS climbs slowly. Address sanitizers and some allocators reserve tens of terabytes of VSZ by design. The one place VSZ genuinely matters is when something enforces a limit on it, notably `RLIMIT_AS` (`ulimit -v`). Capping address space to bound memory use is a common mistake precisely because VSZ counts reservations nobody will ever touch; the process dies on a mapping it was never going to fault in. ## Why RSS is also not "how much memory this process uses" RSS is closer to the truth, but it has three well-known distortions: 1. **Shared pages are counted in full, in every process.** Ten processes sharing a 40 MB library each report those 40 MB, so summing RSS across a process tree can exceed the machine's RAM. The same applies to pages shared with a parent after `fork` until copy-on-write splits them. 2. **File-backed pages are reclaimable.** Part of RSS is page cache for mapped files (`RssFile`), which the kernel can evict without asking the process. The genuinely irreducible part is the anonymous set (`RssAnon`) — heap and stack, which can only go to swap. 3. **Swapped-out pages vanish from RSS.** A process being pushed into swap shows a *falling* RSS while its situation is getting worse, so RSS alone can move in the wrong direction under pressure. For a fair per-process number the kernel offers **PSS** (proportional set size) in `/proc/<pid>/smaps_rollup`: each shared page is divided by the number of processes mapping it, so PSS across all processes sums to roughly the memory in use. ## What to say in the interview Name the demand-paging mechanism, not just the definitions: allocation reserves address space, the first touch causes a fault, and only then is a physical page committed. Then draw the operational conclusion — alerts and limits keyed to VSZ produce false alarms and inexplicable failures, alerts keyed to RSS are usable but double-count sharing, and the OOM killer's own view of a process is built from resident and swap usage, not virtual size.

  • Why is capping a process's memory with `ulimit -v` usually a bad idea?
    `ulimit -v` sets `RLIMIT_AS`, which limits *address space*, not resident memory. It therefore counts reservations that will never occupy RAM — large heap arenas, per-thread stacks, mapped files — so a process can be refused a mapping while using very little physical memory. Runtimes that reserve address space aggressively break under it in ways that look like random allocation failures rather than a memory shortage.
  • If you sum RSS across every process, why can the total exceed the machine's RAM?
    Because shared pages are counted in full for each process that maps them. A shared library, a memory-mapped file, or pages still shared with a parent after fork all appear in several processes' RSS at once. PSS from `/proc/<pid>/smaps_rollup` fixes this by dividing each shared page by its number of sharers, so PSS totals approximate real usage.
  • What is the difference between RssAnon and RssFile, and which one should worry you?
    `RssFile` is resident file-backed memory — mapped executables, libraries and data files — which the kernel can evict and re-read from disk. `RssAnon` is heap and stack with no file behind it; it can only be reclaimed to swap, and with swap disabled it cannot be reclaimed at all. Growth in the anonymous set is what drives a machine towards the OOM killer.

saying these in an interview costs you the question

  • Treats VSZ as the memory a process consumes
  • Adds RSS across processes and calls it total usage
  • Thinks malloc commits physical pages immediately
  • Uses ulimit -v to cap a process's real memory use
  • Assumes falling RSS always means memory pressure eased

context