mpstat 命令详解与参数实测(Ubuntu 22.04)
mpstat 逐参数实测详解:默认 all 汇总十列逐列解读、mpstat 2 3 间隔采样与 Average 语义、-P ALL 逐核与 -P 0 单核、-A 全量(NODE 与软中断)、busy loop 打满单核 100% %usr 实证与 dd 期间 %iowait 对照 vmstat wa,Ubuntu 22.04(sysstat 12.5.2)全部回显实测通过。
mpstat 命令详解与参数实测(Ubuntu 22.04)
目标:全面掌握 mpstat 的每一个常用参数——默认单行 all 汇总逐列解读(%usr/%nice/%sys/%iowait/%irq/%soft/%steal/%guest/%idle)、
-P ALL逐核视图与-P 0单核视图、mpstat 2 3间隔采样、-A全量(含 NODE 与中断)、-u显式开关,并用 busy loop 与 dd 压力实证 %usr 与 %iowait 的变化,全部命令与回显已在 Ubuntu 22.04(sysstat 12.5.2)实测通过。
一、环境信息
- 操作系统:Ubuntu 22.04.5 LTS(x86_64)
- 内核:6.8.0-138-generic(mpstat 报告头首行可见)
- mpstat 版本:sysstat 12.5.2(
mpstat -V实测) - CPU:12 核,Intel(R) Core(TM) i7-14700KF,单路单 NUMA 节点(
lscpu实测:Thread(s) per core: 1、Socket(s): 1、NUMA node(s): 1) - mpstat 与 iostat 同属 sysstat 包,本环境随 iostat 一并安装(安装过程与回显详见《iostat 命令详解与参数实测(Ubuntu 22.04)》2.1 节)
- 演示目录:
/root/demo/iostat/(dd 压力演示复用 iostat 篇的临时大文件,测完即删)
二、命令概览
2.1 安装(mpstat 属于 sysstat 包)
Ubuntu 22.04 默认不预装 mpstat,一条命令安装(与 iostat 同包):
$ apt-get install -y sysstat
实测安装完成后验证:
$ dpkg -l sysstat | tail -1
ii sysstat 12.5.2-2ubuntu0.2 amd64 system performance tools for Linux
$ mpstat -V
sysstat version 12.5.2
(C) Sebastien Godard (sysstat <at> orange.fr)
2.2 语法与测试数据
mpstat 的语法是 mpstat [ options ] [ <interval> [ <count> ] ]:不给 interval 时输出一份「自系统启动以来」的累计平均;给了 interval(如 mpstat 1 3)则每隔 1 秒输出一份增量报告、共 3 份,并在最后追加一行 Average: 汇总。-P { <cpu_list> | ALL } 用于选择报告的处理器粒度。
CPU 压力测试用一个空转循环把单核打满(每个循环占用 1 个核,12 核机器单循环约占总算力 1/12≈8.3%):
$ while :; do :; done & # 后台空转,占满被调度到的那个核
IO 压力测试复用 dd 直写生成的 2 GB 文件(oflag=direct 绕过页缓存,实测写入速度约 650 MB/s):
$ dd if=/dev/zero of=/root/demo/iostat/load.bin bs=1M count=2000 oflag=direct
2000+0 records in
2000+0 records out
2097152000 bytes (2.1 GB, 2.0 GiB) copied, 3.22064 s, 651 MB/s
全部演示结束后 kill 掉空转循环、rm -f /root/demo/iostat/load.bin 清理即可。
2.3 --help 全量输出
mpstat --help 输出全部参数清单(实测逐行照抄):
Usage: mpstat [ options ] [ <interval> [ <count> ] ]
Options are:
[ -A ] [ -n ] [ -T ] [ -u ] [ -V ]
[ -I { SUM | CPU | SCPU | ALL } ] [ -N { <node_list> | ALL } ]
[ --dec={ 0 | 1 | 2 } ] [ -o JSON ] [ -P { <cpu_list> | ALL } ]
💡 说明:mpstat 的参数很少——
-P选核、-I看中断、-N选 NUMA 节点、-A全量、-uCPU 报告开关(默认即开)、-o JSON输出格式。本文第三章逐项实测其中最常用的 6 个。
2.4 版本信息
$ mpstat -V
sysstat version 12.5.2
(C) Sebastien Godard (sysstat <at> orange.fr)
2.5 技术拓展:CPU 观测工具对比
💡 技术拓展:CPU 使用率观测不止 mpstat 一种,常见同类工具横向对比——
工具 视角 特点与适用场景 mpstat CPU(all/逐核/NODE) 唯一原生支持逐核拆分与软中断细分,定位单核打满 top/htop 进程+逐核 实时交互,htop 顶部也有逐核条,但不可脚本化留档 vmstat 系统总览 汇总一行 us/sy/id/wa,粒度粗但够快 sar 历史归档 回放任意历史时段的 CPU 曲线 pidstat -u 进程级 定位「哪个进程」吃 CPU,配合 mpstat 使用 本文主角是 mpstat:需要回答「是不是某个核被打满」「软中断吃掉多少 CPU」时,它的逐核与中断视图不可替代;进程归属再交给 pidstat。
三、参数逐项实测
3.1 默认输出:单行 all 汇总十列解读
不带参数的 mpstat 只输出两行:表头与 all 汇总行,口径是「自系统启动以来」:
$ mpstat
Linux 6.8.0-138-generic (f1034b9326b2) 10/15/26 _x86_64_ (12 CPU)
13:56:50 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
13:56:50 all 19.56 0.00 3.57 0.77 0.00 1.40 0.00 0.00 0.00 74.70
十列逐一解读:
| 列 | 含义 |
|---|---|
| %usr | 用户态占比(不含 nice 调整过的进程) |
| %nice | 低优先级(nice)用户态占比 |
| %sys | 内核态占比 |
| %iowait | 空闲且有未完成磁盘 IO 的时间占比,与 vmstat 的 wa 列同源(实测对照见 3.6) |
| %irq | 处理硬中断的时间占比 |
| %soft | 处理软中断(网络收发、定时器等)的时间占比 |
| %steal | 虚拟化环境下被宿主抢走的时间占比 |
| %guest | 运行虚拟机客户机的时间占比 |
| %gnice | 运行 nice 调整过的虚拟机客户机的时间占比 |
| %idle | 空闲且无 IO 等待的时间占比 |
上例读法:%usr 19.56 + %sys 3.57 + %soft 1.40 ≈ 24.5% 的真实负载,%iowait 0.77 说明磁盘几乎不拖后腿,%idle 74.70 余量充足。
💡 要点:mpstat 的所有百分比加起来恒等于 100%(同一统计口径下各状态互斥),看到哪列异常高就顺着查哪类资源。
3.2 mpstat 2 3:间隔采样与 Average 行
mpstat 2 3 每隔 2 秒采样、共 3 份,末尾自动追加 Average: 行。第一行数据(13:56:52 行)的口径仍是「自系统启动以来」的累计平均,第二行起才是相邻采样之间的实时窗口:
$ mpstat 2 3
Linux 6.8.0-138-generic (f1034b9326b2) 10/15/26 _x86_64_ (12 CPU)
13:56:50 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
13:56:52 all 1.77 0.00 0.51 0.00 0.00 0.51 0.00 0.00 0.00 97.22
13:56:54 all 1.47 0.00 0.51 0.00 0.00 0.42 0.00 0.00 0.00 97.60
13:56:56 all 5.02 0.00 2.24 0.30 0.00 0.89 0.00 0.00 0.00 91.56
Average: all 2.75 0.00 1.08 0.10 0.00 0.60 0.00 0.00 0.00 95.46
三份实时窗口的 %usr 在 1.47~5.02 之间波动(空闲机器的瞬时噪音),Average 行是对实时窗口(不含首份开机快照)求的平均。对比 3.1 的开机平均 %usr 19.56,可以直观体会两种口径的差别。
💡 要点:与 iostat 一样,第一份是开机快照不是实时数据;后续压力实证(3.5)会展示「第一行没变、后面的行才动」的典型形态。
3.3 -P ALL 逐核视图与 -P 0 单核视图
-P ALL 在每个采样时刻先给 all 汇总行、再给 0~11 每个核一行(下例为节省篇幅保留第一窗口与 Average 段):
$ mpstat -P ALL 1 2
Linux 6.8.0-138-generic (f1034b9326b2) 10/15/26 _x86_64_ (12 CPU)
13:56:56 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
13:56:57 all 7.35 0.00 3.55 0.00 0.00 1.27 0.00 0.00 0.00 87.84
13:56:57 0 5.71 0.00 2.86 0.00 0.00 6.67 0.00 0.00 0.00 84.76
13:56:57 1 5.83 0.00 1.94 0.00 0.00 3.88 0.00 0.00 0.00 88.35
13:56:57 2 1.02 0.00 1.02 0.00 0.00 1.02 0.00 0.00 0.00 96.94
13:56:57 3 4.08 0.00 8.16 0.00 0.00 0.00 0.00 0.00 0.00 87.76
13:56:57 4 3.06 0.00 1.02 0.00 0.00 0.00 0.00 0.00 0.00 95.92
13:56:57 5 2.08 0.00 1.04 0.00 0.00 1.04 0.00 0.00 0.00 95.83
13:56:57 6 21.65 0.00 11.34 0.00 0.00 0.00 0.00 0.00 0.00 67.01
13:56:57 7 6.06 0.00 1.01 0.00 0.00 0.00 0.00 0.00 0.00 92.93
13:56:57 8 6.06 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 93.94
13:56:57 9 6.06 0.00 1.01 0.00 0.00 0.00 0.00 0.00 0.00 92.93
13:56:57 10 10.64 0.00 8.51 0.00 0.00 0.00 0.00 0.00 0.00 80.85
13:56:57 11 16.33 0.00 5.10 0.00 0.00 2.04 0.00 0.00 0.00 76.53
Average: CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
Average: all 7.38 0.00 3.04 0.34 0.00 1.22 0.00 0.00 0.00 88.03
Average: 0 12.98 0.00 3.37 0.00 0.00 5.77 0.00 0.00 0.00 77.88
Average: 1 12.75 0.00 2.94 0.00 0.00 2.94 0.00 0.00 0.00 81.37
Average: 2 1.52 0.00 0.51 0.00 0.00 1.02 0.00 0.00 0.00 96.95
Average: 3 8.63 0.00 4.57 0.00 0.00 0.00 0.00 0.00 0.00 86.80
Average: 4 3.05 0.00 1.02 0.00 0.00 0.00 0.00 0.00 0.00 95.94
Average: 5 1.54 0.00 4.10 0.00 0.00 2.56 0.00 0.00 0.00 91.79
Average: 6 12.76 0.00 7.14 1.53 0.00 0.00 0.00 0.00 0.00 78.57
Average: 7 12.12 0.00 3.54 2.53 0.00 0.00 0.00 0.00 0.00 81.82
Average: 8 3.57 0.00 0.51 0.00 0.00 0.00 0.00 0.00 0.00 95.92
Average: 9 3.57 0.00 0.51 0.00 0.00 0.00 0.00 0.00 0.00 95.92
Average: 10 6.25 0.00 4.69 0.00 0.00 0.00 0.00 0.00 0.00 89.06
Average: 11 9.18 0.00 3.57 0.00 0.00 2.04 0.00 0.00 0.00 85.20
逐核价值立刻显现:all 汇总 %usr 只有 7.35%,但 6 号核 %usr 21.65%、%sys 11.34%(%idle 67.01%),0 号核 %soft 6.67%(网络软中断常驻的核)——不拆核的话这些不均匀都被平均值抹平了。
-P 0 只看 0 号核:
$ mpstat -P 0 1 2
Linux 6.8.0-138-generic (f1034b9326b2) 10/15/26 _x86_64_ (12 CPU)
13:56:58 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
13:56:59 0 0.00 0.00 3.85 0.96 0.00 5.77 0.00 0.00 0.00 89.42
13:56:59 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
13:57:00 0 2.91 0.00 3.88 0.00 0.00 4.85 0.00 0.00 0.00 88.35
Average: CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
Average: 0 1.45 0.00 3.86 0.48 0.00 5.31 0.00 0.00 0.00 88.89
-P 0 视图里只有 0 号核的行(没有 all 行),适合长期盯某个特定核(例如绑定了网卡中断的核)。-P 也支持列表与范围,如 -P 0,3,6 或 -P 0-5(语法同 cpu_list)。
💡 要点:
-P ALL是排查「单核瓶颈」的标准姿势——总负载不高但个别核 100% 时,应用往往已经因为抢占该核而卡顿。
3.4 -A 全量:逐核 + NODE + 中断一次看全
-A 等价于 -u -P ALL 再叠加中断统计,输出五个板块:逐核 CPU、NUMA 节点(NODE)、总中断速率(intr/s)、空板块(中断号细分位)、软中断分类(HI/s TIMER/s NET_TX/s NET_RX/s BLOCK/s TASKLET/s SCHED/s RCU/s 等)。下例 -A 1 1(间隔 1 秒采 1 份),节选关键板块:
$ mpstat -A 1 1
Linux 6.8.0-138-generic (f1034b9326b2) 10/15/26 _x86_64_ (12 CPU)
13:57:00 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
13:57:01 all 6.29 0.00 1.76 0.00 0.00 1.01 0.00 0.00 0.00 90.94
13:57:01 0 0.94 0.00 1.89 0.00 0.00 8.49 0.00 0.00 0.00 88.68
13:57:01 1 4.04 0.00 1.01 0.00 0.00 2.02 0.00 0.00 0.00 92.93
13:57:01 2 14.85 0.00 2.97 0.00 0.00 0.99 0.00 0.00 0.00 81.19
13:57:01 3 10.20 0.00 1.02 0.00 0.00 0.00 0.00 0.00 0.00 88.78
13:57:01 4 10.00 0.00 2.00 0.00 0.00 0.00 0.00 0.00 0.00 88.00
13:57:01 5 0.00 0.00 1.02 0.00 0.00 0.00 0.00 0.00 0.00 98.98
13:57:01 6 2.02 0.00 5.05 0.00 0.00 0.00 0.00 0.00 0.00 92.93
13:57:01 7 5.10 0.00 2.04 0.00 0.00 0.00 0.00 0.00 0.00 92.86
13:57:01 8 20.00 0.00 2.00 0.00 0.00 0.00 0.00 0.00 0.00 78.00
13:57:01 9 1.02 0.00 1.02 0.00 0.00 0.00 0.00 0.00 0.00 97.96
13:57:01 10 6.12 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 93.88
13:57:01 11 1.03 0.00 1.03 0.00 0.00 0.00 0.00 0.00 0.00 97.94
13:57:00 NODE %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
13:57:01 all 6.29 0.00 1.76 0.00 0.00 1.01 0.00 0.00 0.00 90.94
13:57:01 0 6.29 0.00 1.76 0.00 0.00 1.01 0.00 0.00 0.00 90.94
13:57:00 CPU intr/s
13:57:01 all 11029.00
13:57:01 0 455.00
13:57:01 1 322.00
13:57:01 2 229.00
13:57:01 3 173.00
13:57:01 4 163.00
13:57:01 5 221.00
13:57:01 6 170.00
13:57:01 7 173.00
13:57:01 8 155.00
13:57:01 9 205.00
13:57:01 10 185.00
13:57:01 11 294.00
13:57:00 CPU HI/s TIMER/s NET_TX/s NET_RX/s BLOCK/s IRQ_POLL/s TASKLET/s SCHED/s HRTIMER/s RCU/s
13:57:01 0 0.00 32.00 0.00 0.00 0.00 0.00 0.00 214.00 0.00 209.00
13:57:01 1 0.00 13.00 0.00 15.00 0.00 0.00 0.00 71.00 0.00 223.00
13:57:01 2 0.00 8.00 0.00 0.00 0.00 0.00 0.00 36.00 0.00 185.00
13:57:01 3 0.00 6.00 0.00 6.00 0.00 0.00 0.00 26.00 0.00 135.00
13:57:01 4 0.00 3.00 0.00 0.00 0.00 0.00 0.00 4.00 0.00 156.00
13:57:01 5 0.00 7.00 0.00 0.00 7.00 0.00 0.00 30.00 0.00 177.00
13:57:01 6 0.00 12.00 0.00 11.00 0.00 0.00 0.00 1.00 0.00 146.00
13:57:01 7 0.00 6.00 0.00 0.00 0.00 0.00 0.00 16.00 0.00 151.00
13:57:01 8 0.00 3.00 0.00 0.00 0.00 0.00 0.00 13.00 0.00 139.00
13:57:01 9 0.00 22.00 0.00 0.00 0.00 0.00 0.00 14.00 0.00 169.00
13:57:01 10 0.00 58.00 0.00 0.00 0.00 0.00 0.00 12.00 0.00 115.00
13:57:01 11 0.00 41.00 0.00 128.00 0.00 0.00 0.00 4.00 0.00 121.00
Average: CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
Average: all 6.29 0.00 1.76 0.00 0.00 1.01 0.00 0.00 0.00 90.94
Average: 0 0.94 0.00 1.89 0.00 0.00 8.49 0.00 0.00 0.00 88.68
Average: 1 4.04 0.00 1.01 0.00 0.00 2.02 0.00 0.00 0.00 92.93
Average: 2 14.85 0.00 2.97 0.00 0.00 0.99 0.00 0.00 0.00 81.19
Average: 3 10.20 0.00 1.02 0.00 0.00 0.00 0.00 0.00 0.00 88.78
Average: 4 10.00 0.00 2.00 0.00 0.00 0.00 0.00 0.00 0.00 88.00
Average: 5 0.00 0.00 1.02 0.00 0.00 0.00 0.00 0.00 0.00 98.98
Average: 6 2.02 0.00 5.05 0.00 0.00 0.00 0.00 0.00 0.00 92.93
Average: 7 5.10 0.00 2.04 0.00 0.00 0.00 0.00 0.00 0.00 92.86
Average: 8 20.00 0.00 2.00 0.00 0.00 0.00 0.00 0.00 0.00 78.00
Average: 9 1.02 0.00 1.02 0.00 0.00 0.00 0.00 0.00 0.00 97.96
Average: 10 6.12 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 93.88
Average: 11 1.03 0.00 1.03 0.00 0.00 0.00 0.00 0.00 0.00 97.94
Average: CPU intr/s
Average: all 11029.00
Average: 0 455.00
Average: 1 322.00
Average: 2 229.00
Average: 3 173.00
Average: 4 163.00
Average: 5 221.00
Average: 6 170.00
Average: 7 173.00
Average: 8 155.00
Average: 9 205.00
Average: 10 185.00
Average: 11 294.00
Average: CPU HI/s TIMER/s NET_TX/s NET_RX/s BLOCK/s IRQ_POLL/s TASKLET/s SCHED/s HRTIMER/s RCU/s
Average: 0 0.00 32.00 0.00 0.00 0.00 0.00 0.00 214.00 0.00 209.00
Average: 1 0.00 13.00 0.00 15.00 0.00 0.00 0.00 71.00 0.00 223.00
Average: 2 0.00 8.00 0.00 0.00 0.00 0.00 0.00 36.00 0.00 185.00
Average: 3 0.00 6.00 0.00 6.00 0.00 0.00 0.00 26.00 0.00 135.00
Average: 4 0.00 3.00 0.00 0.00 0.00 0.00 0.00 4.00 0.00 156.00
Average: 5 0.00 7.00 0.00 0.00 7.00 0.00 0.00 30.00 0.00 177.00
Average: 6 0.00 12.00 0.00 11.00 0.00 0.00 0.00 1.00 0.00 146.00
Average: 7 0.00 6.00 0.00 0.00 0.00 0.00 0.00 16.00 0.00 151.00
Average: 8 0.00 3.00 0.00 0.00 0.00 0.00 0.00 13.00 0.00 139.00
Average: 9 0.00 22.00 0.00 0.00 0.00 0.00 0.00 14.00 0.00 169.00
Average: 10 0.00 58.00 0.00 0.00 0.00 0.00 0.00 12.00 0.00 115.00
Average: 11 0.00 41.00 0.00 128.00 0.00 0.00 0.00 4.00 0.00 121.00
读法:全机中断速率 intr/s 11029 次/秒;0 号核的 %soft 8.49% 主要由 SCHED(214 次/秒)与 RCU(209 次/秒)构成;11 号核的 NET_RX/s 高达 128——网络收发软中断集中在个别核是常态。本机单 NUMA,NODE 板块与 all 完全一致;多路服务器上 NODE 板块能看出跨节点的负载倾斜。
💡 要点:日常快速排查用
-P ALL即可,-A适合做一次性的完整体检或软中断专项分析。
3.5 -u:显式声明 CPU 报告(等价默认行为)
-u 是「输出 CPU 使用率报告」的显式开关,效果与默认完全相同;在 -A 输出太长、或与其他选项组合想控制板块时有用:
$ mpstat -u 1 1 | tail -2
13:57:02 all 5.65 0.00 2.19 0.42 0.00 1.10 0.00 0.00 0.00 90.63
Average: all 5.65 0.00 2.19 0.42 0.00 1.10 0.00 0.00 0.00 90.63
💡 要点:
-A已经隐含-u;单独使用时-u与默认无差别,但明确写出来可让脚本意图更清晰。
3.6 CPU 压力实证 1:busy loop 打满单核(逐核视角)
后台启动一个空转循环,随即 -P ALL 连续采样 3 秒,观察 Average 段(grep 只保留 Average 行):
$ while :; do :; done & sleep 0.5; mpstat -P ALL 1 3 | grep -E "Average"; kill $! 2>/dev/null
Average: CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
Average: all 14.27 0.00 1.37 0.00 0.00 1.37 0.00 0.00 0.00 82.99
Average: 0 1.50 0.00 0.90 0.00 0.00 12.28 0.00 0.00 0.00 85.33
Average: 1 6.35 0.00 0.33 0.00 0.00 1.00 0.00 0.00 0.00 92.31
Average: 2 4.07 0.00 0.34 0.00 0.00 0.34 0.00 0.00 0.00 95.25
Average: 3 2.04 0.00 1.36 0.00 0.00 0.00 0.00 0.00 0.00 96.60
Average: 4 15.10 0.00 1.01 0.00 0.00 0.00 0.00 0.00 0.00 83.89
Average: 5 2.74 0.00 0.34 0.00 0.00 0.34 0.00 0.00 0.00 96.58
Average: 6 11.78 0.00 2.36 0.00 0.00 0.00 0.00 0.00 0.00 85.86
Average: 7 11.78 0.00 3.37 0.00 0.00 0.00 0.00 0.00 0.00 84.85
Average: 8 9.12 0.00 3.04 0.00 0.00 0.00 0.00 0.00 0.00 87.84
Average: 9 0.00 0.00 0.68 0.00 0.00 0.00 0.00 0.00 0.00 99.32
Average: 10 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
Average: 11 6.85 0.00 2.74 0.00 0.00 1.03 0.00 0.00 0.00 89.38
最典型的一幕:10 号核 %usr 100.00、%idle 0.00——空转循环被调度到这个核上,把它整个吃满;其余核照常呼吸(9 号核甚至全程 99.32% 空闲)。这正是「总负载不高、单核已死」的现场,也是 -P ALL 存在的意义。
3.7 CPU 压力实证 2:busy loop 的汇总视图(默认 all)
同一个单循环在默认 all 汇总视角下的样子:
$ while :; do :; done & sleep 0.5; mpstat 1 4 | grep -E "all"; kill $! 2>/dev/null
13:57:07 all 13.50 0.00 3.00 0.08 0.00 2.08 0.00 0.00 0.00 81.33
13:57:08 all 10.19 0.00 1.68 0.59 0.00 1.01 0.00 0.00 0.00 86.52
13:57:09 all 12.99 0.00 2.01 0.67 0.00 1.42 0.00 0.00 0.00 82.90
13:57:10 all 10.22 0.00 0.50 0.00 0.00 1.09 0.00 0.00 0.00 88.19
Average: all 11.73 0.00 1.80 0.34 0.00 1.40 0.00 0.00 0.00 84.73
对照 3.2 空闲时 %usr 1.475.02 的水位,启动单循环后 13.50——涨幅约 8.3 个百分点,恰是该循环占用的 1/12 核算力(100%/12≈8.33%)。单核 100% 在汇总视图里只显示为 +8%,这就是为什么要配合 3.6 的逐核视图。%usr 稳定在 10.19
3.8 %iowait 与 vmstat wa 对照(dd 压力,双工具同窗口并行采样)
dd 直写期间,把 mpstat 与 vmstat 同时挂起采样(vmstat 落到文件、mpstat 走前台,保证两者覆盖同一个时间窗),对照 %iowait 与 wa 两列:
$ dd if=/dev/zero of=/root/demo/iostat/load.bin bs=1M count=2000 oflag=direct & sleep 0.3; vmstat 1 4 > /tmp/vmstat-j2.log 2>&1 & mpstat 1 4 | grep -E "all"; wait; echo "--- vmstat 同窗口输出 ---"; cat /tmp/vmstat-j2.log; rm -f /root/demo/iostat/load.bin
2000+0 records in
2000+0 records out
2097152000 bytes (2.1 GB, 2.0 GiB) copied, 3.22064 s, 651 MB/s
14:02:10 all 1.87 0.00 7.91 1.11 0.00 0.77 0.00 0.00 0.00 88.34
14:02:11 all 3.59 0.00 9.49 2.22 0.00 1.11 0.00 0.00 0.00 83.59
14:02:12 all 1.35 0.00 5.58 2.70 0.00 0.59 0.00 0.00 0.00 89.77
14:02:13 all 1.36 0.00 0.34 0.00 0.00 0.42 0.00 0.00 0.00 97.88
Average: all 2.04 0.00 5.82 1.51 0.00 0.72 0.00 0.00 0.00 89.91
--- vmstat 同窗口输出 ---
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
5 0 1596844 636404 826084 32797944 0 5 41 2490 115 67 19 5 75 1 0
0 1 1596844 626356 826124 32798168 32 0 40 684416 11768 11731 2 9 88 1 0
1 0 1596844 622716 826168 32798572 32 0 36 650392 21392 27098 4 11 84 2 0
1 0 1596844 622596 826196 32798804 0 0 16 543936 11460 11455 1 6 90 3 0
逐秒对照:dd 存续的前三个窗口,mpstat 的 %iowait 为 1.11→2.22→2.70,vmstat 的 wa 列为 1→2→3,bo(每秒写出的块数)高达 684416/650392/543936——两个工具对同一 IO 压力的 CPU 侧响应完全同步;dd 结束后第四个窗口 %iowait 与 wa 同时归零。两者的差别只是采样口径与舍入粒度(mpstat 精确到 0.01%,vmstat 取整)。
💡 要点:
%iowait与wa是同一事件(CPU 空闲但有 IO 未完成)在两个工具里的各自表述;它升高代表存储层可能跟不上,但要确认设备侧状态还得看 iostat 的%util/await。
3.9 错误用法与退出码
给 -P 传一个不存在的核号,mpstat 打印用法摘要并以状态码 1 退出:
$ mpstat -P 99 1 1; echo rc=$?
Usage: mpstat [ options ] [ <interval> [ <count> ] ]
Options are:
[ -A ] [ -n ] [ -T ] [ -u ] [ -V ]
[ -I { SUM | CPU | SCPU | ALL } ] [ -N { <node_list> | ALL } ]
[ --dec={ 0 | 1 | 2 } ] [ -o JSON ] [ -P { <cpu_list> | ALL } ]
rc=1
💡 要点:脚本里可以靠退出码判断 mpstat 是否执行成功(0 成功、1 参数或运行错误),避免把错误用法输出当数据解析。
四、实战示例
4.1 判断「整体慢」还是「单核瓶颈」
只看汇总(数据取自 3.7:all %usr 11.73、%idle 84.73)会以为机器很闲;加逐核视图(数据取自 3.6)立刻看到 10 号核 100%。组合套路:
$ mpstat 1 3 | grep Average # 第一步:看整体水位
$ mpstat -P ALL 1 3 | grep -v all # 第二步:整体有异常或怀疑不均时,逐核下钻
4.2 定位软中断吃 CPU 的核
多核服务器上网络吞吐上不去时,先看 %soft 分布(数据取自 3.3 与 3.4:0 号核 %soft 6.67%/8.49%,其余核多为 0~4%):软中断集中于少数核说明中断亲和性未调优,可用 cat /proc/interrupts 查看中断分布后调整 smp_affinity。
4.3 观察一批 CPU 密集任务对整机的影响
先采基线(3.2 的 1.47~5.02),再启动 N 个空转循环,用 mpstat 2 3 观察 %usr 阶梯上升(单循环 +8.3 个百分点,见 3.7 实测),由此可反推:实际 %usr 涨幅 ÷ 8.3 ≈ 打满的核数。
4.4 与 vmstat/iostat 组合做存储排查
存储卡顿排查三板斧(均已在本文与 iostat 篇实测):
$ mpstat 1 3 # %iowait 是否升高(本文 3.8:1.11→2.70)
$ vmstat 1 3 # wa 列交叉印证,bo 看写出量(3.8:684416 块/秒)
$ iostat -x 1 3 # %util/await/aqu-sz 确认设备侧瓶颈(iostat 篇 3.10)
五、注意事项与常见问题
Q1:为什么第一份报告的数字和后面不是一个量级?
mpstat 给了 interval 时,首份报告(时间戳为第一个采样区间结束时刻)的口径是「自系统启动以来」的累计平均(实测见 3.2:开机平均 %usr 19.56 对比实时窗口 1.47~5.02);第二份起才是实时窗口。排查当下问题只看第二份起的数据,Average: 行也只统计实时窗口。
Q2:%usr 高就一定是应用的问题吗?
不一定。先区分列归属:%usr 是用户态业务代码,%sys 是内核态(系统调用、锁、内存管理),%soft 是软中断(网络收发高峰时常见,实测 0 号核 %soft 8.49% 由 SCHED/RCU 软中断构成,见 3.4),%iowait 是等盘。对应处理方向完全不同。
Q3:所有列都接近 0,但机器明明很卡?
看三个隐藏方向:一是逐核拆分(-P ALL),单核 100% 被平均抹平(实测:单循环在 all 上只显示 +8.3%,见 3.7,但 10 号核 100%,见 3.6);二是 %steal(虚拟机被宿主抢占);三是卡顿可能根本不是 CPU,转 vmstat 的 b 列与 iostat 的 await 查 IO。
Q4:mpstat 的 %iowait 高说明什么?和 iostat 的 %util 什么关系?
%iowait 是 CPU 视角的「空闲但有 IO 没做完」时间占比,%util 是设备视角的「设备忙」时间占比。%iowait 高只是提示存储可能跟不上(实测 dd 期间 1.11→2.70,见 3.8);最终判定要用 iostat 的 %util/await/aqu-sz 三件套(iostat 篇 3.10 实测)。
Q5:-P ALL 的编号从 0 开始还是 1 开始?
从 0 开始(本机 12 核编号 0~11,实测见 3.3/3.4 输出)。引用核号时(如中断亲和性脚本里的 CPU 编号)以 mpstat//proc/cpuinfo 的编号为准,别按 1 计数。
Q6:脚本里解析 mpstat 输出有什么稳妥姿势?
固定用 Average: 行(给 interval 时必出现)作为稳定锚点;加 -o JSON 可直接得结构化输出(本版支持,见 2.3 帮助清单);--dec={0|1|2} 控制小数位。别按空格 split 表头行——列宽会随数值变宽。
六、参考链接
- mpstat 手册页(man7):https://man7.org/linux/man-pages/man1/mpstat.1.html
- Ubuntu 22.04(jammy)mpstat 手册页:https://manpages.ubuntu.com/manpages/jammy/en/man1/mpstat.1.html
- sysstat 项目主页(源码与 FAQ):https://github.com/sysstat/sysstat
- Ubuntu 官方包信息 sysstat:https://packages.ubuntu.com/jammy/sysstat
- 内核文档 procfs stat(mpstat 数据来源):https://www.kernel.org/doc/Documentation/filesystems/proc.rst