mpstat 深入:软中断与单核瓶颈
更新时间:2026-09-19。
mpstat -P ALL能看到每个 CPU 核的时间分布。整体平均很闲、但某一个核被网卡软中断打满,是高网络流量机器的典型隐形瓶颈——平均指标完全看不出来。RSS 机制见网卡多队列。
一、命令与字段
bash
mpstat 1 3 # 整机每 1s
mpstat -P ALL 1 # 每个核(最常用)
mpstat -P 0 1 # 只看 0 号核bash
CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
all 25.0 0.0 12.0 2.0 0.5 3.0 0.0 0.0 0.0 57.5
0 10.0 0.0 8.0 0.0 1.0 85.0 0.0 0.0 0.0 1.0 ← 软中断打满
1 30.0 0.0 10.0 1.0 0.0 1.0 0.0 0.0 0.0 58.0| 列 | 含义 |
|---|---|
| %usr | 用户态 |
| %sys | 内核态(不含中断处理) |
| %irq | 硬中断(hardirq,网卡收包第一阶段) |
| %soft | 软中断(NET_RX/TIMER 等下半部,协议栈处理大头) |
| %iowait | CPU 等待 IO |
| %steal | 虚拟化被 hypervisor 偷取 |
| %idle | 空闲 |
二、网卡中断为什么会集中到单核
收包路径是:网卡硬中断(%irq)→ 触发 NET_RX 软中断(%soft)做协议栈处理。如果网卡只有一个队列,或多队列的中断亲和性都绑在同一个 CPU,那么无论机器多少核,所有报文的收包软中断都压在那一个核上:
- 该核 %soft 接近 100%,其它核很闲;
- PPS(每秒报文数)到顶后开始丢包、延迟抖动,即使总 CPU 才 20%。
三、确认路径
bash
# 1) 找到单核 %soft 异常
mpstat -P ALL 1
# 2) 看网卡中断分布在哪些 CPU(每行是一个队列的 IRQ,列是各核累计次数)
grep -E 'eth0|ens' /proc/interrupts
watch -n1 'grep eth0 /proc/interrupts'
# 3) 看软中断分类计数(NET_RX 是否随流量猛增)
watch -n1 'grep NET_RX /proc/softirqs'
# 4) 网卡队列数与 offload
ethtool -l eth0判断:若 /proc/interrupts 里网卡中断计数几乎只在 CPU0 增长,且 mpstat CPU0 %soft 高,就坐实了中断不均。
四、处理
- 开启/增多队列(RSS):
ethtool -L eth0 combined N,让硬件把流量哈希散到多个队列,见 RSS 与绑核。 - 调中断亲和性:把每个队列的
/proc/irq/<irq>/smp_affinity_list分散到不同核,并对这些 IRQ 让 irqbalance 不要又聚回单核。 - 没有硬件多队列时用 RPS/RFS:软件把收包软中断分散到多核(虚拟网卡常见),配合 ethtool ring/offload。
- 检查 irqbalance 是否把网卡中断错误聚合;低延迟场景可手动绑核并排除这些 IRQ。
五、其它高 %soft/%irq 的来源
- 不只是网卡:TIMER(大量定时)、块设备完成中断、高 PPS 的 UDP/短连接都可能抬高软中断。
- 高 %sys(不是 %soft)伴随大量
cs(vmstat),更偏向系统调用/上下文切换频繁,方向不同。 - 单核 100% 若是 %usr 而非 %soft,那是单线程程序/绑核计算瓶颈,用 perf 而不是调网卡。
坑
- 只看 all 行平均 CPU,漏掉单核软中断打满。
- 开了多队列但不查 /proc/interrupts,中断仍被绑在单核,以为 RSS 生效。
- 把 %soft 高一律当网卡问题,忽略 TIMER/块中断来源,先看 /proc/softirqs 分类。
- 手动绑核后没管 irqbalance,重启或策略刷新后被改回。
总结
mpstat -P ALL 的价值在于暴露单核瓶颈:某核 %irq/%soft 接近 100% 而其它核空闲,通常是网卡收包硬中断和 NET_RX 软中断集中在单核;确认要结合 /proc/interrupts 看队列中断分布、/proc/softirqs 看 NET_RX 增速,再通过开启多队列 RSS、设置 smap_affinity_list 分散中断或用 RPS 软件分摊来解决,同时注意区分软中断、系统调用高和单线程 %usr 满这三类不同瓶颈。