性能排查工具集:5 条可一键走通的场景化链路
你大概有过这种体验:系统报警说"CPU 飙到 90%",你打开文档库,perf 怎么用、top 怎么看、strace 是啥都查得到,但到底先敲哪条、看到什么再换下一条,得自己拿这几篇拼。拼错了就浪费半小时,甚至误判方向。
这份文档就是把这些分散的单工具页,按"问题 → 排查链路"串起来。每个场景给你一张流程图 + 分步命令 + 每步该看什么、异常了往哪拐。你照着走一遍,基本就能从"系统慢"收敛到"某行代码慢"或"某块盘慢"。
如果只想看工具各自的完整用法,单篇在 性能分析工具速查;想知道这些工具为什么谁也替代不了谁,见 compare。
先建立一个核心认知:分诊 → 下钻
不管哪个场景,排查都分成两个阶段,工具也据此分成两类:
- 分诊台(宏观统计工具):top、vmstat、iostat、mpstat、sar、ss。它们告诉你"系统哪个科室不舒服"——CPU 高、IO 高、还是连接堆积。
- CT 扫描(微观剖析工具):perf、strace、gdb。它们告诉你"病灶在代码哪一行"——哪个函数烧 CPU、哪次系统调用最慢。
没有分诊你不知道该扫谁,拿着 perf 大海捞针;没有 CT 你永远只能猜病因。所以下面每条链路都是"分诊在前、下钻在后",顺序别乱。
场景一:CPU 使用率高,到底烧在哪
这是最高频的问题。注意区分"用户态高(业务代码)"和"内核态高(系统调用/锁/缺页)",方向完全不同。
分步走法:
top -H -p <PID>展开线程,找到吃 CPU 的 TID。按1看逐核——如果只有一个核满,是单线程瓶颈,加核没用。- us 高:用
perf top -t <TID>实时看热点函数;要留存就perf record -p <PID> -g -- sleep 30再perf report或导出火焰图。函数级热点只有 perf 给得了,top 只能告诉你进程高。 - sy 高:说明在狂调系统调用或抢锁。先用
strace -c -p <PID>统计 syscall 频次和耗时,再用pidstat -w区分是自愿切换(等 IO)还是非自愿切换(被抢 CPU)。非自愿切换爆高 →perf lock查锁竞争。
落点文档:top · perf · strace · pidstat。
场景二:内存越来越紧,是不是泄漏
内存问题最怕"只看 free 被吓到"——free 小不代表有事,available 才是真可用。
分步走法:
free -h只看available列。它持续下降才是真危险信号。vmstat 1看si/so:都为 0 说明还没开始换页,问题没那么急;持续大于 0 说明内存已经不够、内核在往磁盘搬页,性能会骤降。pidstat -r -p <PID> 1看谁的majflt(主缺页)在涨,cat /proc/<PID>/status | grep VmRSS看 RSS 增长速率——这两步锁定"是不是某个进程在泄漏"。- 若
si/so为 0 但 available 低,看/proc/meminfo:SUnreclaim涨 = 内核态泄漏(驱动/socket),用slabtop定位;Dirty涨 = 脏页堆积,用 iotop 找写入进程。
落点文档:free · vmstat · pidstat · 内存概念见 mmap。
场景三:IO 等待高,磁盘还是进程
wa 高(top 里 %Cpu 的 wa)容易让人直接甩锅给磁盘,但 SSD/NVMe 下 %util 已经失真,得看延迟和队列。
分步走法:
iostat -x 1:重点看await(平均 IO 延迟)和aqu-sz(平均队列深度)。await高 +aqu-sz > 2持续 = 请求在排队,盘真忙。- 机械盘看
%util:近 100% 就是打满。SSD/NVMe 别看%util——多队列下它会失真,改看r/s、w/s、rkB/s是否接近盘带宽上限。 iotop -o找DISK READ/WRITE最高的进程;要更细就pidstat -d -p <PID> 1看该进程的 IO 延迟(iodelay)。
落点文档:iostat · iotop · pidstat。
场景四:网络卡,连接堆积还是丢包
网络问题分两端:连接状态(TIME-WAIT 堆积、listen 队列溢出)和链路质量(重传、丢包、软中断分布)。
分步走法:
ss -s一眼看连接状态分布。TIME-WAIT 上万 = 短连接过多;CLOSE-WAIT 堆积 = 应用忘了close()(连接泄漏),这个最该警惕。- 连接正常但吞吐上不去:
sar -n ETCP 1看 TCP 重传率(>1% 说明丢包严重);sar -n EDEV 1看rxdrop/txdrop(网卡丢包);mpstat -P ALL看%soft是否集中在 CPU0(网卡没开多队列/RPS 没配)。
落点文档:ss · mpstat · lsof(查端口/句柄占用)。
场景五:进程崩溃了(段错误 / abort / 卡死)
这条和上面四条不同——它属于崩溃线而非性能线。进程已经死了,工具链从"实时观测"变成"事后还原现场"。
分步走法:
- 先
dmesg | grep -i "killed process"确认是不是 OOM Killer 干的——如果是,看谁oom_score高,那是下一个被杀的候选。 - 段错误/abort:前提是
ulimit -c已开、core 文件已生成。用gdb <binary> core加载,bt看崩溃时的调用栈,info registers看寄存器现场。 - 死锁(进程卡死不退出):
gdb -p <PID>attach 上去看各线程栈,或perf lock看谁持锁。
落点文档:core-dump · gdb · 崩溃原理见 signals。
五条链路一眼对照
| 现象 | 第一步(分诊) | 异常拐向 | 下钻工具 |
|---|---|---|---|
| CPU 高 | top -H | us 高 → 函数热点 / sy 高 → syscall | perf / strace |
| 内存紧 | free -h 看 available | si/so>0 → 泄漏 / SUnreclaim 涨 → 内核泄漏 | pidstat / slabtop |
| IO 慢 | iostat -x | await 高 → 盘忙 / %util 失真 → 看带宽 | iotop / pidstat -d |
| 网络卡 | ss -s | CLOSE-WAIT 堆 → 连接泄漏 / 重传高 → 丢包 | sar / mpstat |
| 进程崩 | dmesg 看 OOM | 段错误 → core / 死锁 → attach | gdb / perf lock |
一句话总结
排查不是"会多少工具",而是"知道先掏哪把刀"。这五条链路把分散的工具按"分诊 → 下钻"串成顺序,照着走,你就能从"系统慢"一步步收敛到"某行代码慢"或"某块盘慢"——这也是 性能分析工具速查 那张平面表格想表达、但没直接画出来的东西。
想做长期复盘(问题已经过去),用 sar 回看历史趋势;想知道每条命令的完整选项和字段含义,回到各单篇文档深挖。