Ubuntu 20.04 进程占用 100% CPU 如何使用 perf 定位热点函数?

文章导读
在 Ubuntu 20.04 上遇到进程 CPU 占用率飙升至 100% 时,最推荐的做法是先通过 top 确认进程 ID,再使用 perf record 采集采样数据,最后通过 perf report 查看热点函数调用栈。
📋 目录
  1. 命令速用版
  2. 为什么会这样
  3. 分步处理
  4. 怎么验证是否生效
  5. 常见坑
  6. 参考来源
A A

在 Ubuntu 20.04 上遇到进程 CPU 占用率飙升至 100% 时,最推荐的做法是先通过 top 确认进程 ID,再使用 perf record 采集采样数据,最后通过 perf report 查看热点函数调用栈。

先说结论:perf 是 Linux 内核自带的性能分析工具,适合在生产环境低开销地定位 CPU 热点,但需要确保内核版本与工具版本匹配。

  • 先定位:确认具体是哪个进程和线程占用 CPU,避免误杀正常高负载业务。
  • 先做:安装与当前内核版本一致的 linux-tools 包,使用 perf record 采集调用栈。
  • 再验证:根据热点函数优化代码或配置后,观察 CPU 负载是否回落。

命令速用版

以下命令假设你已经知道目标进程的 PID,例如 12345。

Ubuntu 20.04 进程占用 100% CPU 如何使用 perf 定位热点函数?
# 1. 安装 perf 工具(需匹配当前内核版本)
sudo apt update
sudo apt install linux-tools-generic linux-tools-$(uname -r)

# 2. 确认进程 ID 和占用最高的线程
 top -H -p 12345

# 3. 采集 30 秒的性能数据(-g 表示记录调用栈)
sudo perf record -p 12345 -g -- sleep 30

# 4. 查看分析报告
sudo perf report

为什么会这样

当某个进程 CPU 占用达到 100%(通常指单核满载)时,说明该进程正在密集执行计算任务或陷入死循环。操作系统调度器虽然能切换任务,但无法告诉你是哪行代码在空转。perf 基于硬件事件采样(如 CPU 时钟周期),每隔固定时间记录一次当前执行的指令指针,累积足够样本后就能统计出哪些函数占用了最多的 CPU 时间片。相比 strace 等追踪系统调用的工具,perf 对用户态代码的内部逻辑可见性更好,且开销通常在 5% 以内,适合线上临时排查。

分步处理

第一步:确认目标进程
使用 top 命令找到 CPU 占比最高的进程 PID。如果是因为某个线程导致,按 top 界面中的 H 键开启线程视图,找到占用最高的线程 ID(TID)。

第二步:安装匹配的工具
Ubuntu 20.04 默认可能未安装 perf 或版本不匹配。运行 uname -r 查看内核版本,确保安装的 linux-tools 包版本与之对应。如果版本不一致,perf record 可能会报错提示 kernel map 失败。

Ubuntu 20.04 进程占用 100% CPU 如何使用 perf 定位热点函数?

第三步:采集数据
执行 sudo perf record -p <PID> -g -- sleep 30。这里 -p 指定进程,-g 记录调用图,sleep 30 控制采集时长。生产环境建议控制在 30-60 秒,避免生成过大的数据文件。

第四步:分析报告
运行 sudo perf report 进入交互式界面。按百分比排序,找到占用率最高的函数符号。如果是业务代码符号,直接定位源码;如果是库函数或内核函数,结合日志分析是否涉及锁竞争或系统调用。

Ubuntu 20.04 进程占用 100% CPU 如何使用 perf 定位热点函数?

怎么验证是否生效

优化代码或配置后,重启服务并观察监控面板。使用 top -p <PID> 再次查看 CPU 占比,确认是否从 100% 降至正常水平。同时检查应用日志,确认没有因优化引入新的错误或延迟。公开资料中没有看到可靠的量化数据表明 perf 本身能降低 CPU,它只是定位工具,效果取决于后续的代码修复。

常见坑

1. 权限不足:perf 需要 root 权限或配置 /proc/sys/kernel/perf_event_paranoid 参数,否则无法采集内核态数据。
2. 符号缺失:如果报告显示大量十六进制地址而非函数名,说明缺少调试符号。对于自有代码,编译时请加上 -g 参数。
3. 生产影响:虽然 perf 开销小,但在极高负载下仍可能加剧竞争。建议在业务低峰期操作,或先在测试环境复现。
4. 内核 mismatch:Ubuntu 升级内核后,旧的 linux-tools 可能失效,需重新安装对应版本工具包。

参考来源