Home / Alt manpages / proc_vmstat(5)

  • proc_vmstat(5)
  • File format
  • linux

Read /proc/vmstat Without Guessing What the Counters Mean

You will finish with a small, repeatable way to inspect /proc/vmstat, select counters worth watching, and compare two readings without changing the system. Allow about ten minutes. You need a shell and a Linux host with procfs mounted. The examples use Linux 6.8.0-139-generic and the local manpages package version 6.7-2; field availability and values vary with the kernel configuration and workload.

This is a read-only workflow. It needs no sudo, does not edit a sysctl, and does not flush caches or alter memory pressure. The file is a live kernel interface, not a configuration file despite being documented by proc_vmstat(5).

1. Confirm that the interface is available

Read the file directly and check that it contains two whitespace-separated columns. The first is a counter name and the second is its current integer value:

$ test -r /proc/vmstat && echo readable
readable
$ sed -n '1,8p' /proc/vmstat
nr_free_pages 276613
nr_zone_inactive_anon 414883
nr_zone_active_anon 2136706
nr_zone_inactive_file 3259520
nr_zone_active_file 641888
nr_zone_unevictable 6911
nr_zone_write_pending 1712
nr_mlock 6911

Your numbers will be different, and the field order or field set may differ. A missing file normally means procfs is not mounted in this environment, or that a container has a restricted view of it. Check the mount rather than trying to create the file:

$ findmnt /proc
TARGET SOURCE FSTYPE OPTIONS
/proc  proc   proc   rw,nosuid,nodev,noexec,relatime

Checkpoint: you should have a readable file with one name-value pair per line. Do not assume that a short output is an error: the manpage says some fields are conditional on kernel build options.

2. Look up names before interpreting values

Start with the installed manual, which is the version-specific contract on this machine:

$ man 5 proc_vmstat

The manual identifies /proc/vmstat as available since Linux 2.6.0 and lists fields with their introduction versions where known. It also warns that fields can depend on kernel configuration and that those requirements can change between kernel versions. The long list is not a promise that every host will expose every name.

Use a narrow query when you need a particular counter. This example selects page allocation and fault counters if they exist:

$ awk '$1 == "pgfault" || $1 == "pgmajfault" || $1 == "pgalloc_normal" { print }' /proc/vmstat
pgalloc_normal 10485613929
pgfault 26519204718
pgmajfault 2370800

An absent line is meaningful evidence about this kernel, not a zero. If a script needs a field, test for its presence and handle the missing case explicitly. Avoid parsing by line number because optional fields and kernel changes can move everything after them.

3. Separate current levels from activity counters

Some names describe a current population, such as nr_free_pages, nr_mlock or nr_free_cma. Others are cumulative event counters, such as pgfault, pgmajfault, pswpin and pswpout. The spelling is a useful clue, but do not attach a unit or meaning that the installed manual does not establish.

For example, nr_free_cma is explicitly described as the number of free Contiguous Memory Allocator pages. The manpage describes nr_kernel_stack as memory allocated to kernel stacks, but does not turn every field into a universal byte or kilobyte measurement. Treat the integer as a kernel statistic and consult the relevant kernel documentation before presenting it as a graph with units.

Checkpoint: write down the exact names you are using and whether your question needs a point-in-time level or a change over time. This prevents the common mistake of treating a large lifetime total such as pgfault as current memory pressure.

4. Compare two snapshots for recent activity

A delta is usually more useful than one lifetime total. Take two snapshots around a short workload interval and subtract the second column. This shell example records only named counters in temporary files, then prints the increase:

$ awk '$1 == "pgfault" || $1 == "pgmajfault" || $1 == "pswpin" || $1 == "pswpout" { print $1, $2 }' /proc/vmstat > /tmp/vmstat-before
$ sleep 5
$ awk '$1 == "pgfault" || $1 == "pgmajfault" || $1 == "pswpin" || $1 == "pswpout" { print $1, $2 }' /proc/vmstat > /tmp/vmstat-after
$ awk 'NR == FNR { before[$1] = $2; next } { printf "%s: %d\n", $1, $2 - before[$1] }' /tmp/vmstat-before /tmp/vmstat-after
pgfault: 1842
pgmajfault: 0
pswpin: 0
pswpout: 0

The output is illustrative: your workload and interval control the values. A major fault delta of zero does not mean paging is impossible; it means this five-second sample saw no increase in that counter. If a field appears in one snapshot but not the other, the simple subtraction is not safe, so make the script reject missing keys before using it for monitoring.

The files are disposable temporary measurements. Remove them when you are finished:

$ rm -- /tmp/vmstat-before /tmp/vmstat-after

This is the only state-changing command in the guide, and it removes only the two files created above. If you used different paths, verify them with ls -l before deleting anything.

5. Diagnose misleading readings

Readings can change while you are looking at them. A single command samples the file at one point, while a monitoring loop measures a moving workload. Keep the interval and workload consistent when comparing runs.

Do not infer swap activity from pswpin or pswpout alone without checking the kernel and the rest of the system state. Pair the sample with tools such as free, vmstat or application metrics, and record the kernel release with uname -r. These counters are evidence for a diagnosis, not a standalone verdict.

If a field you expected is absent, check the exact running kernel and its configuration. The manpage calls out conditional groups including NUMA, VM event counters, transparent huge pages, compaction and memory ballooning. Do not substitute a similarly named field without confirming that it answers the same question.

Done means

  • /proc/vmstat is readable and you know whether procfs is available in the current environment.
  • You used field names rather than line positions and checked the installed proc_vmstat(5) manual.
  • You distinguished current levels from cumulative counters before interpreting a value.
  • You compared snapshots over a stated interval when asking about recent activity.
  • You treated optional fields and changing values as normal kernel-version and workload differences.
  • The temporary snapshot files are removed, or you have deliberately retained them for a documented comparison.