Read NUMA Memory Placement with numastat
By the end of this guide you will be able to read the kernel's per-node NUMA counters, inspect one process's resident memory, and produce a compact report that is useful on a wide machine. The commands are observational: they read kernel interfaces and do not change CPU affinity, memory policy or process state.
The route
Jump straight to the step you need, or tick off Done means at the end.
You need the numastat command from the numactl package. This guide was checked with numactl 2.0.18 on a Linux host. Allow about 10 minutes for the first pass. You do not need root for the examples, although access to another user's process data can depend on the host's /proc permissions.
Checkpoint 1: confirm the command and its default report
- Check the installed version.
$ numastat -V
2.0.18
The version is worth recording with a performance report because output details and available options belong to the installed numactl build. If the command is missing, install the distribution package named numactl using your normal package-management process. That is an administrative change, so it is outside the read-only workflow here.
- Run the report with no options.
$ numastat
node0
numa_hit 20524362786
numa_miss 0
numa_foreign 0
interleave_hit 30
local_node 20525666111
other_node 0
The default report uses pages, not megabytes. The columns are NUMA nodes. numa_hit counts allocations made on the intended node, while numa_miss counts allocations made elsewhere. A miss is paired with a numa_foreign count on the node where the allocation was intended. local_node and other_node describe allocation while a process was running on the allocating node or another node. These are cumulative kernel counters, so they describe activity since the counters were initialised, not a fresh sample interval.
Do not read a zero in a counter as proof that a host has no NUMA issue. A single-node machine has no remote node to expose, and a quiet workload may simply not have produced the event. Also, these counters are pages, while the process and system reports below use megabytes.
Checkpoint 2: inspect system memory by node
- Request the meminfo-like system view.
$ numastat -m
This prints rows similar to /proc/meminfo, with a column for each node and a total column. It is the useful starting point when the question is, "Where is the resident system memory?" Values include rows such as MemTotal, MemFree, Active, Inactive, AnonPages, FilePages and Slab. The exact node count and values are host-specific, so save the output rather than relying on a fixed column layout.
- Combine megabyte units with a narrower display.
$ numastat -m -c -z
-c shrinks columns based on their contents and rounds displayed memory to the nearest megabyte. -z removes rows and columns that contain only zero values. On a host with many nodes this can make the difference between a readable terminal report and a screen full of empty columns. A value can still display as zero after rounding even when its underlying value is non-zero.
Checkpoint 3: find a process's allocation
- Inspect the shell that launches the command.
$ numastat -p "$$"
Per-node process memory usage (in MBs) for PID 2836398 (numastat)
Node 0 Total
--------------- ---------------
Heap 0.01 0.01
Stack 0.02 0.02
Private 1.69 1.69
---------------- --------------- ---------------
Total 1.71 1.71
$$ is expanded by the shell to its own PID. Depending on how your shell launches the final command, the displayed process name can be the shell or numastat. To inspect a different process, replace it with a numeric PID:
$ numastat -p 1234
Replace 1234 with a PID that exists on your host. The process report is based on resident pages described through /proc/<PID>/numa_maps; it is not a complete accounting of virtual address space. A process that exits while it is being read can produce incomplete or unavailable data. Retry with a live PID before treating that as a NUMA result.
- Search command lines by text when the PID is not known.
$ numastat -p qemu
$ numastat libvirt kvm qemu
Non-numeric arguments are treated as fragments to search for in process command lines. The second form asks for several fragments; the -p flag is optional in this case. A broad fragment can match helper processes as well as the service you intended, so check the reported names and PIDs. Use -v when you need detail for each matching process rather than only aggregate lines for multiple processes:
$ numastat -p qemu -v
Checkpoint 4: sort and capture repeatable output
- Sort the largest consumers to the top.
$ numastat -m -s
$ numastat -p qemu -s2
With no node number, -s sorts by the total column. -s2 sorts by node 2. The node number must touch the option, with no space. Because -s accepts an optional argument, put it last in a combined option string. For example, use -mcs, not -msc, when combining memory, compact and sort modes.
- Set an explicit output width when redirecting or logging.
$ NUMASTAT_WIDTH=120 numastat -m > /tmp/numastat-memory.txt
$ sed -n '1,20p' /tmp/numastat-memory.txt
Interactive output normally targets an 80-column terminal and may use the resize command when available. Redirected output can contain long lines. NUMASTAT_WIDTH gives a stable width for logs and comparisons. The file above is a temporary, non-destructive capture; remove it when it is no longer needed with rm -- /tmp/numastat-memory.txt.
Common traps
- Mixing units: the no-option report is in pages.
-npresents the original statistics in megabytes, while-mpresents system memory in megabytes. Do not compare a raw default number directly with a process total. - Assuming a snapshot: the default counters accumulate. For a simple live view, use
watch -n1 numastat, but remember that each screen is still a cumulative reading. Stop it withCtrl-C. - Over-interpreting rounding: compact mode rounds values, and zero-looking rows can still contain a small non-zero value. Remove
-cwhen the distinction matters. - Using a name that matches too much: process patterns search command lines, not service-manager unit names. Prefer a verified PID for an incident report.
- Expecting a tuning tool: numastat reports resident memory and allocation counters. It does not move memory or change policy. Use a separate, reviewed NUMA policy tool when you intentionally need to change placement.
Done means
- You recorded the installed numastat version.
- You can distinguish page-based default counters from megabyte reports.
- You inspected system memory with
-mand a process with-p. - You can reduce wide output with
-c, hide empty data with-z, and sort with-s. - You know that the examples read state only and that a process disappearing during inspection should be checked again.