DevOpsInterviewPrep logo
← 🐧 Systems Foundations
Foundational

Linux virtual memory and page cache: read memory pressure correctly

Separate virtual address space, resident memory and page cache. Use reclaim evidence and container limits to explain memory pressure without guessing at a leak.

TL;DR: Virtual address space, resident memory and reclaimable cache answer different questions. Diagnose the memory boundary that is under pressure, then distinguish useful caching from allocations that cannot be reclaimed quickly enough.

Three views of one process

A process reserves virtual addresses for mappings such as its heap, shared libraries and files. Reserving an address range does not mean every page currently occupies physical RAM. Resident set size, or RSS, counts resident pages mapped by that process, including shared pages that may also appear in another process's RSS. Adding every process's RSS can double-count shared memory. Proportional set size, or PSS, apportions shared pages among their mappings.

The kernel also keeps file data in the page cache. A repeated read can use those cached pages instead of repeating storage I/O. Clean file-backed pages can often be discarded and read again later; dirty pages need appropriate writeback first. The kernel's /proc reference describes these process and system accounting fields, including smaps_rollup and the available-memory estimate.

rendering diagram…

Low free memory can be healthy

Imagine a 32 GiB server with only 1 GiB marked free after repeatedly reading a large dataset. Its available-memory estimate is 12 GiB, application latency is stable, and no sustained memory stalls appear. Buying a larger host solely because the free-memory graph looks low is a weak recommendation. The cache is doing useful work, and the kernel estimates that much of the occupied memory can be made available.

Now change the observations. Available memory falls toward 1 GiB, latency rises, and direct reclaim keeps application threads busy trying to obtain pages. The same headline percentage has a different operational meaning. A large cache can coexist with trouble when pages are actively reused, dirty writeback is slow, or the workload's non-reclaimable demand is too large.

MeasurementUseful questionCommon misreading
Virtual sizeHow much address space is mapped?All mapped space is physical RAM
RSS / PSSWhat is resident, and how is sharing counted?Sum of RSS equals host consumption
Available-memory estimateWhat could support more work without swapping?A guarantee that every allocation will succeed
Reclaim and pressureIs obtaining memory delaying useful work?Cache size alone proves pressure
Container usage and limitIs this workload near its own boundary?Spare host memory prevents local OOM

These figures are accounting views, so do not add every row in a dashboard and expect an exact memory identity. Some categories overlap. Keep the collection scope and units attached to each observation.

Containers add another limit

A service limited to 2 GiB can suffer an out-of-memory event even when the node has substantial spare memory. On cgroup v2, memory.current, memory.stat and memory.events provide usage composition and limit-event evidence; memory.high and memory.max serve different control purposes. Check the service's actual cgroup rather than assuming the shell's group is the service's group. The memory controller documentation defines these interfaces.

A useful interview answer compares two hypotheses. If an application's anonymous memory grows after each equivalent workload cycle and does not settle after collection or cleanup, investigate retained objects and allocator behavior. If file-backed cache grows while repeated reads become faster and pressure remains low, the growth may be productive. Neither observation alone proves or disproves an application leak. Compare equal traffic, input sizes and process lifetimes before attributing a trend.

Avoid dropping the host's caches as a first response. That removes evidence and can increase read latency while the cache warms again. Prefer reducing admitted work, fixing an allocation pattern, or adjusting a justified limit with enough node headroom. Validate the chosen action against the same load that exposed the problem.

Read-only inspection and a self-check

This local Linux example reads only system totals and the inspecting shell's own process accounting. Production investigation should substitute the affected process after confirming its identity and access permissions.

free -h
cat /proc/meminfo
cat /proc/$$/smaps_rollup
cat /proc/pressure/memory

The PSI interface reports time stalled by memory contention. Track changes alongside throughput; a quiet sample after the traffic stops cannot explain what happened at peak load.

Suppose a container shows 1.8 GiB usage against a 2 GiB limit, while its node has 10 GiB available. Its usage contains 1.4 GiB anonymous memory and 0.4 GiB file cache. Can you promise a new 0.5 GiB allocation will succeed?

No. Even if all 0.4 GiB were reclaimable immediately, the simplified arithmetic leaves only 0.6 GiB before considering other concurrent allocations and accounting overhead. Actual reclaimability and allocation timing are unknown. Inspect local pressure and limit events, establish the peak working set, and test with headroom. The node's available figure does not override the container limit.

Memory leak diagnosis compares repeated workload cycles and includes a local retention experiment to distinguish live objects from resident pages.

RELATED CONCEPTS
PRACTICE THIS IN REAL QUESTIONS