CPU 性能问题通常表现为系统响应变慢、应用延迟升高或服务器负载飙升。分析 CPU 性能,核心任务是回答三个问题:哪些进程在消耗 CPU?它们在执行什么代码?是否存在不合理的使用模式? 下面从常用工具、分析流程和典型场景展开,力求实用、可复现。
1. 快速总览:确定 CPU 的总体状态
先用全局工具快速判断 CPU 是否饱和、竞争在哪里。
uptime:查看过去 1、5、15 分钟的平均负载。若平均负载持续高于 CPU 逻辑核数,说明有进程在排队等待 CPU。
uptime
# 12:34:56 up 10 days, 2:15, 3 users, load average: 4.52, 3.89, 3.12
top或htop:动态查看总 CPU 利用率(us 用户态、sy 内核态、id 空闲、wa 等待 I/O、hi/si 硬/软中断)。重点关注us和sy的占比:业务进程消耗用户态 CPU,驱动或系统调用频繁会导致sy升高。
top
# 按 1 展开各 CPU 核心,按 P 按 CPU 用量排序,按 q 退出。
vmstat 1:每秒输出一次系统整体运行队列(r列)、上下文切换(cs)、中断(in)和 CPU 时间分布。r值持续高于 CPU 核数表示 CPU 成为瓶颈。
vmstat 1
# r b swpd free buff cache si so bi bo in cs us sy id wa st
# 3 0 0 162340 43212 1453421 0 0 15 8 152 310 45 12 40 3 0
当 wa(I/O 等待)很高时,CPU 可能并非计算瓶颈,而是等待磁盘或网络,应转而检查存储或 I/O 子系统。
2. 定位高消耗进程和线程
top/htop的进程列表直接显示 CPU 占用率(%CPU),可以按P键排序。pidstat 1(来自sysstat包):按进程查看每秒 CPU 使用率,并区分用户态(%usr)、内核态(%system)、客户机(%guest)等。对后台守护进程特别有用。
pidstat 1
# 每 1 秒打印一次进程 CPU 统计。
- 若需要看线程级别(如 Java 多线程),使用
pidstat -t -p <PID> 1或top -H -p <PID>。
3. 挖出 CPU 消耗的具体函数:使用 perf
知道哪个进程高消耗后,需要知道它到底在忙什么——是在做浮点运算、字符串处理,还是频繁系统调用?
perf 是 Linux 内核内置的性能分析器,采样开销低,适合生产环境。
- 实时采样进程:
perf top -p <PID>
动态展示占用 CPU 最多的函数,结果类似 top,但聚焦到代码级。
- 记录并报告(最常用):
perf record -p <PID> -g -- sleep 30 # 采样 30 秒,-g 记录调用栈
perf report # 交互式查看报告
报告中会列出函数及其 CPU 占比。若开启 -g,可展开函数调用的父子关系,直观看到热点路径。
结合火焰图工具(如 Brendan Gregg 的 FlameGraph 脚本),可将 perf record 的数据转换为一目了然的 SVG 图形,快速定位顶层热点。
4. 区分用户态与内核态消耗
- 如果
%system高,说明进程大量执行系统调用或触发内核活动。用strace -c -p <PID>统计系统调用次数和耗时,寻找不合理的调用(如短时间读写几百字节而不是批量操作)。 - 使用
perf也可以区分:采样时默认混合用户和内核态,报告时选择分列查看;或使用perf record -e cycles:u -p <PID>仅采样用户态,比较与全态的差异。
注意:strace 高负载时可能拖慢进程,谨慎在生产环境中长时间使用,可先用 perf 定位问题再针对性补充。
5. 多核利用与负载分布
mpstat -P ALL 1:查看各 CPU 核心利用率,揪出“单核心瓶颈”(某个核心 100% 而其他空闲)。常见于单线程程序或中断绑定不当。
mpstat -P ALL 1
- 如果有单个进程占满一个核心,其他核心却很闲,需要检查应用是否能并行化、线程数设置是否合理。
6. 实时性和延迟分析
当 CPU 并非始终满载,但偶尔出现尖峰导致业务抖动时:
- 使用
perf sched record和perf sched latency分析调度延迟,查明进程是否长时间得不到 CPU。 - 对于软实时需求(如音频、高频交易),可配合
chrt调整进程调度策略(SCHED_FIFO或SCHED_RR)并分配优先级。
7. 典型诊断流程
假设用户反馈应用响应慢,按以下步骤排查:
uptime→ 平均负载 > CPU 核数,负载高。top→ 看到us高,wa低,CPU 本身在忙碌。top或pidstat→ 确定进程myapp(PID 3456)占用约 80% CPU。perf top -p 3456→ 发现大量 CPU 消耗在regex_compile函数,推测正则表达式编译被频繁调用。- 验证:检查代码,发现请求内部每次都构造 regex,移至初始化阶段编译一次复用,CPU 占用骤降。
8. 工具速查表
| 场景 | 工具 | 要点说明 |
|------------------------------|------------------------------|------------------------------------------|
| 全局负载判断 | uptime, vmstat, top | 关注 r、平均负载和 idle |
| 进程/线程 CPU 占用 | top -H, pidstat -t | 结合 -p 指定 PID |
| 函数级热点分析 | perf top, perf record/report | 使用 -g 抓取调用栈,配合火焰图更直观 |
| 系统调用统计 | strace -c, perf stat | perf stat 可得到指令、缓存等硬件计数 |
| 各核心均衡度 | mpstat -P ALL | 发现单核心瓶颈 |
| 调度与中断异常 | perf sched, /proc/interrupts | 检查中断分布和调度延迟 |
| 快速实时监控(脚本友好) | sar -u 1(来自 sysstat) | 后台记录 CPU 历史数据 |
掌握这些基础手段,已经足以诊断大部分生产环境中的 CPU 性能问题。关键是形成“从全局到局部、从进程到函数”的分析习惯,并用数据验证优化效果。