性能分析工具入门:系统工具与 Profiling 工具
做性能优化,第一步不是调代码,而是找到瓶颈在哪。
总不能凭空猜测吧。你得靠工具说话。我早期做 SDK 性能排查时,就是拿着一堆不熟悉的工具瞎试,走了不少弯路。后来慢慢捋清楚了,其实就两大类:系统工具 和 Profiling 工具。
系统工具:先看全局趋势
系统工具相当于体检报告。不打开也能大概知道身体有没有问题。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
top 默认按 CPU 排序。按 Shift+M 可以改成按内存排。按 1 能看到每个 CPU 核心的使用率。你想想看,排查内存泄漏时很有用。
htop — 更舒服的交互
htop 是 top 的增强版。颜色区分,支持鼠标点击,能直接杀掉进程。但需要单独安装(apt install htop)。
我个人更喜欢 htop 的场景是:同时监控多核 CPU、内存条、交换分区,一眼就能看出谁在吃资源。它还支持树状视图(F5 键),能看到进程父子关系。嗯,排查僵尸进程时特别好使。
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 卡。你看,一个大方向就有了。
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 就只能看到函数名,不知道上下文。明白吧,排查性能回归时,调用链就是破案线索。
-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 次,明显有问题
工具选型速查表
| 场景 | 推荐工具 | 原因 |
|---|---|---|
| 实时看 CPU 占用 | top / htop | 直观,无需安装 |
| 快速诊断内存不足 | vmstat + free | 能看出 swap 活动 |
| IO 瓶颈 | iostat + vmstat | wa 列 + 磁盘队列 |
| 函数级热点 | perf top / record | 低开销,调用链 |
| 动态追踪系统调用 | bpftrace (DTrace) | 无侵入,灵活 |
| 容器内性能隔离 | cgroupstats + vmstat | 不受 namespace 干扰 |
工具不在多,在于会用。我刚开始做性能排查时,看到一个 CPU 高就冲上去调代码,结果调完后问题还在,因为根本原因在 IO。后来学会先用系统工具扫全局,再用 Profiling 工具定位函数,效率提升了好几倍。