3. CPU性能分析:CPU使用率、上下文切换、运行队列长度、中断处理、软中断与硬中断

说到CPU性能分析,很多人第一反应就是看使用率。嗯,这没错,但远远不够。我见过太多工程师,看到CPU使用率不高就觉得系统没问题,结果业务延迟高得离谱。今天咱们就把CPU性能这块掰开揉碎了讲清楚。

3.1 CPU使用率:别被数字骗了

CPU使用率,说白了就是CPU忙活的时间占比。但这里有个坑——使用率高不等于性能差,使用率低也不等于性能好

我遇到过这样一个案例:某服务CPU使用率只有30%,但请求延迟动不动就上秒。一查才发现,大量时间花在了等待锁上,CPU其实在空转。所以你看,光看使用率是不够的。

我们通常把CPU使用率拆成几个维度来看:

  • 用户态使用率(user):应用程序跑的时间
  • 系统态使用率(system):内核干活的时间
  • 等待I/O(iowait):等磁盘、网络的时间
  • 软中断(softirq):处理软中断的时间
  • 硬中断(hardirq):处理硬中断的时间
  • 偷取时间(steal):虚拟机场景下被宿主机偷走的时间

怎么查这些数据?top 命令是最直接的:

# 查看CPU使用率详情
top -n 1

# 更细粒度的查看
cat /proc/stat | grep cpu

关键判断标准

  • user 高 → 应用层瓶颈,考虑优化代码或扩容
  • system 高 → 系统调用频繁,或者内核态有开销
  • iowait 高 → 磁盘或网络I/O是瓶颈
  • steal 高 → 宿主机资源争抢,考虑迁移虚拟机

3.2 上下文切换:看不见的开销

上下文切换,就是CPU从一个任务切到另一个任务。每次切换都要保存寄存器、刷新TLB,这开销可不小。我做过测试,一次上下文切换大概要花几微秒,如果每秒切换几万次,那CPU时间就全耗在这上面了。

怎么看上下文切换频率?用 vmstat 或者 pidstat

# 每秒查看一次上下文切换
vmstat 1

# 查看具体进程的上下文切换
pidstat -w 1

vmstat 输出里的 cs 列就是上下文切换次数。如果这个值持续很高(比如每秒几万次),那就要警惕了。

我的经验:我曾经优化过一个网关服务,上下文切换每秒高达8万次。后来发现是线程池开得太大了,几百个线程抢几个CPU。把线程数降到CPU核数的2倍后,切换降到了5000次/秒,吞吐量翻了一倍。

上下文切换分三种:

  • 进程切换:不同进程之间切换,开销最大
  • 线程切换:同一进程的线程切换,开销稍小
  • 中断处理:硬中断和软中断导致的切换

3.3 运行队列长度:CPU到底够不够用

运行队列长度,就是等待CPU的进程数。这个指标比CPU使用率更能反映CPU是否饱和。

举个例子:CPU使用率100%但运行队列只有1,说明CPU虽然忙但没积压。反过来,CPU使用率50%但运行队列有10,说明CPU已经处理不过来了,大量进程在排队。

怎么看运行队列?

# 查看运行队列长度
cat /proc/loadavg

# 或者用 sar 查看历史数据
sar -q 1 5

/proc/loadavg 的第一列就是1分钟的平均运行队列长度。一般来说,这个值超过CPU核数的2倍,就说明CPU不够用了。

注意:运行队列长度和CPU使用率要结合起来看。我见过有人只看使用率,觉得80%还行,结果运行队列已经排到20了。这种场景下,加CPU核数比优化代码更有效。

3.4 硬中断:硬件在敲门

硬中断是硬件设备发给CPU的信号,比如网卡收到数据包、磁盘完成读写。CPU收到硬中断后,会暂停当前工作去处理。

硬中断处理要求快,所以内核里硬中断处理程序通常只做最必要的事,比如把数据拷贝到缓冲区,然后触发软中断让内核慢慢处理。

怎么看硬中断?

# 查看每个CPU的中断分布
cat /proc/interrupts

# 查看网卡中断
cat /proc/interrupts | grep eth

如果某个CPU的中断数特别多,说明中断负载不均衡。这时候可以用 irqbalance 或者手动绑定中断到不同CPU。

实战经验:我调优过一个高并发网关,发现CPU0的中断数比其他核高10倍。原因是所有网卡中断都默认发到了CPU0。后来用 echo 1 > /proc/irq/xxx/smp_affinity 把中断分散到多个核,整体吞吐提升了30%。

3.5 软中断:内核的“后台任务”

软中断是内核用来处理那些不紧急但耗时的任务的。比如网络协议栈的处理、定时器、任务调度等。

硬中断只负责“收快递”,软中断负责“拆快递”。这样设计的好处是,硬中断能快速返回,系统响应更及时。

怎么看软中断?

# 查看软中断统计
cat /proc/softirqs

# 查看软中断CPU使用率
top -n 1 | grep si

常见的软中断类型:

  • NET_TX/NET_RX:网络收发处理
  • BLOCK:块设备I/O
  • TASKLET:任务小精灵,用于延迟执行
  • SCHED:调度器相关
  • HRTIMER:高精度定时器

如果 si 占比高,说明软中断处理成了瓶颈。网络密集型服务最常见的就是 NET_RX 软中断过高。

避坑指南:我曾经遇到一个案例,某服务软中断CPU使用率高达40%。排查发现是网卡开启了GRO(Generic Receive Offload)但驱动有bug,导致软中断里做了大量无效的数据包合并。关闭GRO后,软中断降到5%。所以,有时候硬件卸载功能不一定都是好事。

3.6 知识体系总览

下面这张图把CPU性能分析的核心指标串起来了,方便你理解它们之间的关系:

CPU性能分析核心指标 CPU性能分析 CPU使用率 user / system iowait / steal softirq / hardirq 上下文切换 进程切换 线程切换 中断切换 运行队列长度 loadavg 1/5/15 sar -q 中断处理 硬中断 软中断 中断均衡 核心思路:先看使用率,再看队列,最后查中断 四个指标要联动分析,单一指标容易误判

3.7 实战:快速定位CPU瓶颈

说了这么多,到底怎么用?我总结了一套排查流程:

  1. 第一步top 看整体,确认是 user 高、system 高还是 iowait 高
  2. 第二步vmstat 1 看上下文切换和运行队列,判断是否饱和
  3. 第三步cat /proc/interrupts/proc/softirqs 看中断分布
  4. 第四步perf top 或者 火焰图 定位热点函数

记住:CPU性能分析不是看单一指标,而是看一组指标的组合。使用率低+运行队列长,说明CPU在空转(锁竞争、I/O等待)。使用率高+运行队列短,说明CPU在高效工作。使用率高+运行队列长,说明CPU不够用了。

嗯,CPU性能分析这块内容就这些。下次遇到CPU问题,别光盯着使用率了,把上下文切换、运行队列、中断这些指标都拉出来看看,你会发现很多隐藏的问题。


专注资料整理