mpstat Command in Linux: Per-CPU and Interrupt Statistics

mpstat from the sysstat package reports per-processor CPU utilization, NUMA node stats, and interrupt rates on Linux. Use it to find hot CPUs, IRQ load, and uneven scheduling across cores.

Published

Updated

Read time 11 min read

Reviewed byDeepak Prasad

mpstat command output showing per-CPU utilization, NUMA node statistics, and interrupt rates on Linux
About mpstat from the sysstat package reports per-processor CPU utilization, NUMA node stats, and interrupt rates on Linux. Use it to find hot CPUs, IRQ load, and uneven scheduling across cores.
Tested on Rocky Linux 10.2; sysstat 12.7.6; kernel 6.12.0-211.28.1.el10_2.x86_64
Package sysstat (apt/deb) · sysstat (dnf/rpm)
Man page mpstat(1)
Privilege none
Distros

Most Linux distributions (sysstat package).

Per-process CPU: pidstat.

Related guide

mpstat is part of the sysstat toolkit. It prints CPU utilization per logical processor, optional NUMA node breakdowns, and interrupt statistics from /proc/stat, /proc/interrupts, and /proc/softirqs. On a busy host, one overloaded CPU while others sit idle often shows up here before it is obvious in a single global average.

Tested on: Rocky Linux 10.2; sysstat 12.7.6; kernel 6.12.0-211.28.1.el10_2.x86_64.


mpstat — quick reference

Default CPU report and intervals

When to use Command
Global CPU utilization since boot mpstat
Sample every N seconds until Ctrl+C mpstat N
N samples at M-second intervals mpstat M N
Show sysstat version mpstat -V

Per-processor and NUMA views

When to use Command
One row per CPU plus global all average mpstat -P ALL
Single CPU only (CPU 0 is first) mpstat -P 0
Several CPUs by list or range mpstat -P 0,1 or mpstat -P 0-3
CPU utilization by NUMA node mpstat -n
Stats for one NUMA node mpstat -N 0
All NUMA nodes mpstat -N ALL
Show CORE, SOCK, NODE topology columns mpstat -P ALL -T

Interrupt statistics (-I)

When to use Command
Total interrupts per second (summary) mpstat -I SUM
Per hardware IRQ from /proc/interrupts mpstat -I CPU
Per software IRQ from /proc/softirqs mpstat -I SCPU
Hardware + software + summary mpstat -I ALL

Combined and output format

When to use Command
CPU, NUMA, and all interrupt reports mpstat -A
CPU report only (same as default) mpstat -u
Hotplugged vCPU detection mpstat -H
Integer percentages (no decimals) mpstat --dec=0
One decimal place mpstat --dec=1
JSON for scripts and dashboards mpstat -o JSON
JSON with per-CPU rows mpstat -P ALL -o JSON

mpstat — command syntax

Synopsis from sysstat 12.7.6:

text
mpstat [ -A ] [ --dec={ 0 | 1 | 2 } ] [ -H ] [ -n ] [ -u ] [ -T ] [ -V ]
       [ -I { SUM | CPU | SCPU | ALL } ] [ -N { node_list | ALL } ]
       [ -o JSON ] [ -P { cpu_list | ALL } ] [ interval [ count ] ]

With no activity flag selected, mpstat prints the CPU utilization report (-u). The first sample without an interval averages since boot; pass interval and count for live windows. Install the package with sudo dnf install sysstat on RHEL-family hosts or sudo apt install sysstat on Debian and Ubuntu.


mpstat — column guide

Column Meaning
%usr Time running user-space code (normal priority)
%nice Time running niced user processes
%sys Time in kernel mode (syscalls, not including interrupts)
%iowait Time the CPU was idle while the system had an outstanding disk-I/O request. Treat it as an approximate signal, especially per CPU on multicore systems.
%irq Time servicing hardware interrupts
%soft Time servicing softirqs
%steal Time stolen by the hypervisor (VMs)
%guest / %gnice Guest CPU time (virtualized workloads)
%idle Truly idle time

All displayed utilization fields—%usr, %nice, %sys, %iowait, %irq, %soft, %steal, %guest, %gnice, and %idle—should total approximately 100%, allowing for rounding. mpstat subtracts guest time from its displayed %usr and %nice values before reporting %guest and %gnice separately, so the displayed columns can be added without double-counting guest time. A single CPU at high %sys or %irq while all looks fine is a common sign of uneven load or IRQ affinity issues.


mpstat — command examples

Essential Default global CPU snapshot

Run mpstat with no flags when you want one global CPU line since boot.

bash
mpstat

Sample output:

text
Linux 6.12.0-211.28.1.el10_2.x86_64 (ldap1.example.com) 	07/18/2026 	_x86_64_	(2 CPU)

11:39:57 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
11:39:57 PM  all    3.71    0.00    8.94    0.96    9.81    1.40    0.00    0.00    0.00   75.17

The all row averages every logical CPU. High %irq here means interrupt handling is a noticeable slice of CPU time across the box.

Essential Live samples with interval and count

Pass interval and count to watch CPU during a job or deployment window.

bash
mpstat 1 2

Sample output:

text
Linux 6.12.0-211.28.1.el10_2.x86_64 (ldap1.example.com) 	07/18/2026 	_x86_64_	(2 CPU)

11:39:57 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
11:39:58 PM  all    0.00    0.00    1.00    0.00    1.50    0.00    0.00    0.00    0.00   97.50
11:39:59 PM  all    0.51    0.00    0.00    0.00    2.02    0.51    0.00    0.00    0.00   96.97
Average:     all    0.25    0.00    0.50    0.00    1.76    0.25    0.00    0.00    0.00   97.24

Each numbered line covers one second; Average: is the mean across the interval samples, not since boot.

Essential Per-CPU breakdown (-P ALL)

Use -P ALL when you suspect one core is hot while the global average hides it.

bash
mpstat -P ALL

Sample output:

text
Linux 6.12.0-211.28.1.el10_2.x86_64 (ldap1.example.com) 	07/18/2026 	_x86_64_	(2 CPU)

11:39:59 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
11:39:59 PM  all    3.71    0.00    8.94    0.96    9.81    1.40    0.00    0.00    0.00   75.18
11:39:59 PM    0    4.73    0.00    5.33    0.58   12.64    1.24    0.00    0.00    0.00   75.49
11:39:59 PM    1    2.60    0.00   12.87    1.38    6.74    1.57    0.00    0.00    0.00   74.84

CPU 1 shows higher %sys than CPU 0 in this snapshot — worth correlating with process affinity or IRQ placement.

Common One processor only (-P 0)

Filter to a single CPU when you already know which core to watch.

bash
mpstat -P 0

Sample output:

text
Linux 6.12.0-211.28.1.el10_2.x86_64 (ldap1.example.com) 	07/18/2026 	_x86_64_	(2 CPU)

11:39:59 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
11:39:59 PM    0    4.73    0.00    5.33    0.58   12.64    1.24    0.00    0.00    0.00   75.49

Combine with an interval during a pinned workload: mpstat -P 0 1 5.

Common NUMA node CPU stats (-n and -N)

On NUMA hardware, -n rolls up utilization by memory node; -N limits output to specific nodes.

bash
mpstat -N ALL

Sample output:

text
Linux 6.12.0-211.28.1.el10_2.x86_64 (ldap1.example.com) 	07/18/2026 	_x86_64_	(2 CPU)

11:40:21 PM NODE    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
11:40:21 PM  all    3.70    0.00    8.92    0.96    9.79    1.40    0.00    0.00    0.00   75.22
11:40:21 PM    0    3.70    0.00    8.92    0.96    9.79    1.40    0.00    0.00    0.00   75.22

This lab VM has one NUMA node, so all and 0 match. On multi-socket servers, compare nodes to identify uneven CPU utilization across NUMA nodes. Use numastat or hardware performance counters when you need to investigate local-versus-remote memory access.

Common Interrupt rate summary (-I SUM)

-I SUM prints total interrupts per second — a quick IRQ health check before diving into per-vector detail.

bash
mpstat -I SUM

Sample output:

text
Linux 6.12.0-211.28.1.el10_2.x86_64 (ldap1.example.com) 	07/18/2026 	_x86_64_	(2 CPU)

11:40:01 PM  CPU    intr/s
11:40:01 PM  all   1139.89

Pair with -P ALL when IRQ load is uneven across CPUs: mpstat -I SUM -P ALL 1 3.

Common Hardware and software IRQs (-I CPU and -I SCPU)

-I CPU lists each hardware IRQ from /proc/interrupts; -I SCPU lists softirq types from /proc/softirqs.

bash
mpstat -I SCPU | head -6

Sample output:

text
Linux 6.12.0-211.28.1.el10_2.x86_64 (ldap1.example.com) 	07/18/2026 	_x86_64_	(2 CPU)

11:40:21 PM  CPU       HI/s    TIMER/s   NET_TX/s   NET_RX/s    BLOCK/s IRQ_POLL/s  TASKLET/s    SCHED/s  HRTIMER/s      RCU/s
11:40:21 PM    0       0.00      36.65       0.00       7.22      50.44       0.00       0.01      45.09       0.00      97.55
11:40:21 PM    1       0.00      49.70       0.00      19.16     108.58       0.00       0.13      45.17       0.00      83.36

High BLOCK/s or NET_RX/s often tracks storage or network driver activity on that CPU.

Advanced Full report bundle (-A)

-A is shorthand for -n -u -I ALL and implies -N ALL -P ALL unless you override them on the command line.

bash
mpstat -A | head -20

Sample output:

text
Linux 6.12.0-211.28.1.el10_2.x86_64 (ldap1.example.com) 	07/18/2026 	_x86_64_	(2 CPU)

11:40:01 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
11:40:01 PM  all    3.71    0.00    8.94    0.96    9.81    1.40    0.00    0.00    0.00   75.18
11:40:01 PM    0    4.73    0.00    5.33    0.58   12.64    1.24    0.00    0.00    0.00   75.49
11:40:01 PM    1    2.60    0.00   12.87    1.38    6.73    1.57    0.00    0.00    0.00   74.85

11:40:01 PM NODE    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
11:40:01 PM  all    3.71    0.00    8.94    0.96    9.81    1.40    0.00    0.00    0.00   75.18
11:40:01 PM    0    3.71    0.00    8.94    0.96    9.81    1.40    0.00    0.00    0.00   75.18

11:40:01 PM  CPU    intr/s
11:40:01 PM  all   1139.90

Use this during deep triage; for daily checks, mpstat -P ALL 1 5 is usually enough.

Advanced CPU topology columns (-P ALL -T)

-T adds CORE, SOCK, and NODE identifiers when the kernel exposes them. Pair it with -P ALL so each logical CPU gets its own row with topology values.

bash
mpstat -P ALL -T

Sample output:

text
Linux 6.12.0-211.28.1.el10_2.x86_64 (ldap1.example.com) 	07/18/2026 	_x86_64_	(2 CPU)

11:46:47 PM  CPU CORE SOCK NODE    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
11:46:47 PM  all                   3.73    0.00    8.89    0.98    9.77    1.39    0.00    0.00    0.00   75.24
11:46:47 PM    0    0    0    0    4.75    0.00    5.28    0.58   12.56    1.23    0.00    0.00    0.00   75.60
11:46:47 PM    1    1    0    0    2.61    0.00   12.84    1.41    6.72    1.57    0.00    0.00    0.00   74.84

The global all row has no single topology assignment, so its topology fields remain blank. The individual CPU rows selected by -P ALL show the logical core, socket, and NUMA node reported by the kernel.

Advanced Rounding and JSON export (--dec and -o JSON)

--dec controls decimal places; -o JSON feeds monitoring pipelines.

bash
mpstat --dec=0

Sample output:

text
Linux 6.12.0-211.28.1.el10_2.x86_64 (ldap1.example.com) 	07/18/2026 	_x86_64_	(2 CPU)

11:40:01 PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle
11:40:01 PM  all       4       0       9       1      10       1       0       0       0      75

For JSON:

bash
mpstat -o JSON | head -15

Sample output:

text
{"sysstat": {
	"hosts": [
		{
			"nodename": "ldap1.example.com",
			"sysname": "Linux",
			"release": "6.12.0-211.28.1.el10_2.x86_64",
			"machine": "x86_64",
			"number-of-cpus": 2,
			"date": "07/18/2026",
			"statistics": [
				{
					"timestamp": "11:40:01 PM",
					"cpu-load": [
						{"cpu": "all", "usr": 3.71, "nice": 0.00, "sys": 8.94, "iowait": 0.96, "irq": 9.81, "soft": 1.40, "steal": 0.00, "guest": 0.00, "gnice": 0.00, "idle": 75.18}

Pipe through jq to extract one field in automation.


mpstat — when to use / when not

Use mpstat when Use something else when
  • You need per-CPU utilization, not one global average
  • IRQ or softirq load might explain high %sys
  • You want NUMA-node CPU breakdown on multi-socket hosts
  • You are sampling during a fixed interval with mpstat 1 10
  • You need which process uses CPU → pidstat or top
  • You need memory, swap, and run queue → vmstat
  • You need disk throughput and %utiliostat
  • You need historical CPU data from yesterday → sar

mpstat vs top vs vmstat

mpstat top vmstat
Focus Per-CPU and IRQ stats Live process list Memory, I/O, run queue
Per-CPU rows Yes (-P ALL) Per-CPU summary line Single CPU column set
Interrupt detail Yes (-I) No No
Best question "Is one CPU or IRQ vector hot?" "Which PID is burning CPU?" "Is the box swapping or I/O bound?"

For a broader CPU troubleshooting walkthrough, see how to check CPU utilization in Linux.


Command One line
iostat Disk and global CPU I/O wait
vmstat Memory, swap, and system-wide CPU
sar Historical sysstat archives
pidstat Per-process CPU and I/O

Browse the full index in our Linux commands reference.


mpstat — interview corner

What is mpstat?

mpstat is a sysstat tool that reports processor-related statistics: CPU utilization per logical CPU, optional NUMA placement, and interrupt rates.

bash
mpstat -P ALL 1 3

A strong answer is:

"mpstat from sysstat shows per-CPU utilization and interrupt stats. -P ALL breaks out each core; interval sampling gives live averages instead of since-boot numbers."

What do %iowait, %irq, and %soft mean?

%iowait is idle CPU time while the system had an outstanding disk-I/O request — an approximate signal, not a direct storage bottleneck indicator. %irq is hardware interrupt handling; %soft is softirq processing (network stack, block layer, timers).

A strong answer is:

"High iowait can support an I/O-wait hypothesis, but it does not identify the device or prove that storage is the bottleneck. Correlate it with iostat, pidstat -d, application latency, and I/O pressure. High irq or soft on one CPU often means interrupt affinity or driver load on that core."

Why does the first mpstat line differ from interval samples?

Without an interval, mpstat averages since boot. With mpstat 1 5, each sample line covers one second and Average: summarizes only those samples.

A strong answer is:

"With no interval, mpstat reports averages since boot. Adding an interval and count makes it report live sampling windows. Unlike vmstat and iostat, mpstat does not print a leading since-boot report when a non-zero interval is supplied."

mpstat vs top for CPU troubleshooting?

top shows which processes consume CPU. mpstat shows how each CPU spends time, including interrupt columns top does not break out per core.

A strong answer is:

"top for the process list; mpstat -P ALL when global CPU looks fine but you suspect one hot core or IRQ load."

mpstat vs sar?

mpstat specializes in current per-CPU, NUMA, and interrupt statistics. sar can report live system activity using an interval and count or read previously saved sysstat archives.

A strong answer is:

"Use mpstat for focused live per-CPU and interrupt analysis. Use sar for broader system statistics, either live with an interval and count or historically from saved archives. RHEL-family systems normally use /var/log/sa, while Debian and Ubuntu commonly use /var/log/sysstat."


Troubleshooting

Symptom Likely cause Fix
command not found sysstat not installed sudo apt install sysstat or sudo dnf install sysstat
Only all row on UP machine Uniprocessor host Expected — per-CPU rows need multiple logical CPUs
-I SCPU missing or empty Kernel older than 2.6.31 Upgrade kernel or use -I SUM / -I CPU only
-N shows one node Single-node hardware or VM Normal on laptops and small VMs; use -P ALL instead
-H looks like default output No hotplugged vCPUs present -H adds value only when vCPUs are hot-added
High %steal on a VM Host oversubscription Move workload or resize the guest; check hypervisor capacity

References

Rohan Timalsina

is a technical writer and Linux enthusiast who writes practical guides on Linux commands and system administration. He focuses on simplifying complex topics through clear explanations.