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性能分析的核心指标串起来了,方便你理解它们之间的关系:
3.7 实战:快速定位CPU瓶颈
说了这么多,到底怎么用?我总结了一套排查流程:
- 第一步:
top看整体,确认是 user 高、system 高还是 iowait 高 - 第二步:
vmstat 1看上下文切换和运行队列,判断是否饱和 - 第三步:
cat /proc/interrupts和/proc/softirqs看中断分布 - 第四步:
perf top或者火焰图定位热点函数
记住:CPU性能分析不是看单一指标,而是看一组指标的组合。使用率低+运行队列长,说明CPU在空转(锁竞争、I/O等待)。使用率高+运行队列短,说明CPU在高效工作。使用率高+运行队列长,说明CPU不够用了。
嗯,CPU性能分析这块内容就这些。下次遇到CPU问题,别光盯着使用率了,把上下文切换、运行队列、中断这些指标都拉出来看看,你会发现很多隐藏的问题。