性能分析工具入门:系统工具与 Profiling 工具

做性能优化,第一步不是调代码,而是找到瓶颈在哪。

总不能凭空猜测吧。你得靠工具说话。我早期做 SDK 性能排查时,就是拿着一堆不熟悉的工具瞎试,走了不少弯路。后来慢慢捋清楚了,其实就两大类:系统工具 和 Profiling 工具。

性能分析工具分类 系统监控工具 • top 实时进程视图 • htop 增强版交互 • vmstat 系统整体指标 • iostat / netstat Profiling 工具 • perf 内核级采样 • DTrace 动态追踪 • gprof / valgrind • flamegraph 火焰图 系统工具看整体,Profiling 工具挖细节 两者配合使用效果最佳 ※ 具体选哪个工具,取决于你想查 CPU、内存、IO 还是函数级热点

系统工具:先看全局趋势

系统工具相当于体检报告。不打开也能大概知道身体有没有问题。CPU 是否爆了?内存够不够?IO 堵不堵?

top — 最基础也够用

几乎所有 Linux 系统都自带。不用装任何东西,直接敲 top 就行。

top - 14:23:45 up 12 days,  3:12,  2 users,  load average: 4.51, 3.28, 2.15
Tasks: 345 total,   1 running, 344 sleeping
%Cpu(s): 25.3 us,  8.7 sy,  0.0 ni, 65.4 id,  0.3 wa,  0.3 hi,  0.0 si
KiB Mem :  16166368 total,   312456 free,  8923456 used,  6920456 buff/cache
KiB Swap:  8388604 total,  8388604 free,        0 used.  6345678 avail Mem
  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
 1234 ubuntu    20   0 1024M  256M   12M S  45.0  1.6   5:23.45 my_sdk_process
 5678 ubuntu    20   0  512M  128M    8M S  12.3  0.8   2:10.32 app_worker
我习惯的看板顺序: load average(负载)、%wa(等待 IO)、%us(用户态 CPU)。如果 wa>10,大概率是磁盘背锅。

top 默认按 CPU 排序。按 Shift+M 可以改成按内存排。按 1 能看到每个 CPU 核心的使用率。你想想看,排查内存泄漏时很有用。

htop — 更舒服的交互

htop 是 top 的增强版。颜色区分,支持鼠标点击,能直接杀掉进程。但需要单独安装(apt install htop)。

我个人更喜欢 htop 的场景是:同时监控多核 CPU、内存条、交换分区,一眼就能看出谁在吃资源。它还支持树状视图(F5 键),能看到进程父子关系。嗯,排查僵尸进程时特别好使。

我曾经踩过的坑: 在容器环境里 using top,发现 CPU 显示 100%,但 host 上实际负载很低。后来才意识到容器里看到的 /proc 是 namespace 隔离的。htop 在容器里也能用,但要挂载 host 的 /proc。这种情况最好用 cat /sys/fs/cgroup/cpu/cpuacct.usage 来看真实用量。

vmstat — 轻量级整体快照

vmstat 输出的数据密度高,适合快速扫一眼系统瓶颈。典型用法:

$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  0      0 312456  23456 6920456    0    0    12    45  345  678 25  8 65  2  0
 1  0      0 310567  23456 6920456    0    0     8    32  332  654 23  7 68  2  0

关键列要读懂:

  • r — 正在运行的进程数(不含 IO 等待)。如果长期大于 CPU 核心数,说明 CPU 撑不住了。
  • b — 不可中断睡眠进程数。IO 或锁竞争。
  • si/so — swap 换入换出。只要有数字,内存就不够了。
  • wa — CPU 等待 IO 的时间百分比。这通常是磁盘背锅。

我记得有一次 SDK 集成后,用户反馈视频卡顿。我用 vmstat 一看,wa 飙到 30%,si/so 非零。排查下去发现是 SDK 频繁写日志到慢速 SD 卡。你看,一个大方向就有了。

建议养成习惯: 跑性能测试前,先开一个终端跑 vmstat 1,记录基线。测试后对比变化,能快速定位是新加代码拖了 IO 还是网络。

Profiling 工具:钻进函数内部

系统工具只能告诉你“哪里难受”,但 Profiling 工具能告诉你“哪行代码在作妖”。

perf — Linux 自带的神器

perf 基于内核采样,开销极低。我最常用的是 perf top 和 perf record。

# 实时看当前谁在吃 CPU
$ sudo perf top

# 采样记录一段时间,然后生成报告
$ sudo perf record -g -p <PID> -- sleep 30
$ sudo perf report

-g 开启调用链,能看出热点函数是被谁调用的。没有 -g 就只能看到函数名,不知道上下文。明白吧,排查性能回归时,调用链就是破案线索。

一个小技巧: perf 采样默认按 CPU 周期。如果你怀疑是 cache miss 造成性能差,可以改成 -e cache-misses:
sudo perf record -e cache-misses -g -p <PID> -- sleep 10
这样只记录 cache miss 发生的点,更容易找到内存访问模式的问题。

DTrace — 动态追踪的老法师

DTrace 最早在 Solaris 上出名,后来移植到 Linux(通过 bpftrace 或者 SystemTap)。它不修改程序,不重启,直接动态插入探测点。

举个例子,我曾在排查一个 SDK 导致的高频 syscall 时,用 DTrace 抓到了某库每秒调用 gettimeofday 几万次——这完全没必要。

# 用 bpftrace(Linux 上的 DTrace 等价工具)统计 syscall
$ sudo bpftrace -e 'kprobe:do_sys_open { @[comm] = count(); }'
Attaching 1 probe...
^C

@[my_sdk]: 45678
@[java]: 1234
# 可以看到 my_sdk 每秒打开文件 45678 次,明显有问题
注意: DTrace 类工具在高频率触发时,如果 probe 逻辑写太复杂,会产生可观的开销,本身成为瓶颈。我曾经因为一个循环中加了个无关的 probe,导致 SDK 延迟增加 50%。所以“观察”行为本身要轻量。

工具选型速查表

场景 推荐工具 原因
实时看 CPU 占用 top / htop 直观,无需安装
快速诊断内存不足 vmstat + free 能看出 swap 活动
IO 瓶颈 iostat + vmstat wa 列 + 磁盘队列
函数级热点 perf top / record 低开销,调用链
动态追踪系统调用 bpftrace (DTrace) 无侵入,灵活
容器内性能隔离 cgroupstats + vmstat 不受 namespace 干扰

工具不在多,在于会用。我刚开始做性能排查时,看到一个 CPU 高就冲上去调代码,结果调完后问题还在,因为根本原因在 IO。后来学会先用系统工具扫全局,再用 Profiling 工具定位函数,效率提升了好几倍。