2. 性能检测工具链:Linux perf、top、htop、iostat、vmstat 实战
说实话,很多做性能优化的同学,一上来就盯着代码看。我当年也犯过这个错。后来带我的老大哥说了一句话,我一直记着:「先看系统,再看代码,最后看算法。」
什么意思呢?就是你的程序跑在操作系统上,系统资源就是它的「土壤」。土壤不行,苗再好也长不高。所以这一章,咱们就把 Linux 下最常用的几把「锄头」摸清楚。
2.1 先搭个「全景图」
工欲善其事,必先利其器。下面这张图,是我自己梳理的 Linux 性能检测工具全景。你把它存脑子里,以后排查问题就有方向了。
2.2 top / htop:第一眼诊断
我个人习惯,登录服务器第一件事就是敲 top。它就像医院的「生命体征监测仪」,看一眼就知道病人还有没有救。
2.2.1 top 核心指标解读
| 指标 | 含义 | 警戒线 |
|---|---|---|
| %us | 用户态 CPU 占用 | > 70% 说明应用在忙 |
| %sy | 内核态 CPU 占用 | > 30% 可能有系统调用瓶颈 |
| %wa | 等待 IO 的 CPU 占比 | > 20% 磁盘大概率是瓶颈 |
| %id | 空闲 CPU | < 10% 说明 CPU 吃紧 |
| load average | 1/5/15 分钟平均负载 | 超过 CPU 核数说明排队 |
小技巧: top 里按
1 可以看每个 CPU 核的使用情况。我曾经遇到一个 Java 服务,整体 CPU 才 40%,但有一个核跑到了 100%。这就是典型的「单线程瓶颈」。
2.2.2 htop:top 的「可视化升级版」
htop 说白了就是 top 的图形化版本。它支持鼠标操作、彩色显示、树形进程视图。我个人更喜欢 htop,因为一眼就能看到哪个进程在「吃」资源。
# 安装 htop
sudo apt install htop -y
# 直接运行
htop
htop 的几个常用快捷键:
- F6:按 CPU/内存/IO 排序
- F9:直接杀掉进程
- F5:树形视图,看父子进程关系
注意: htop 默认不显示线程。如果你要排查多线程应用的问题,记得按
H 键切换线程视图。我曾经排查过一个 Nginx 性能问题,就是因为没开线程视图,找了半天才发现是某个 worker 线程卡住了。
2.3 vmstat:内存与进程的「X 光机」
vmstat 是我最常用的内存分析工具。它不仅能看内存,还能看进程状态、CPU 上下文切换、IO 等待。你想想看,一个命令能看这么多东西,是不是很划算?
# 每隔 1 秒输出一次,共输出 5 次
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 1623452 1234 567890 0 0 12 34 456 789 12 3 85 0 0
2.3.1 关键字段解读
| 字段 | 含义 | 实战经验 |
|---|---|---|
| r | 正在运行的进程数(就绪队列) | 如果持续 > CPU 核数,说明 CPU 不够用 |
| b | 不可中断睡眠的进程数 | 数值大说明 IO 有瓶颈 |
| si / so | swap 换入/换出 | 只要不是 0,内存就不够了 |
| cs | 上下文切换次数/秒 | 超过 10 万次要考虑优化 |
核心判断逻辑:
- 如果
r很大但b很小 → CPU 瓶颈 - 如果
b很大且wa很高 → IO 瓶颈 - 如果
si/so不为 0 → 内存不足,赶紧加内存或优化内存使用
2.4 iostat:磁盘 IO 的「听诊器」
我记得有一次线上告警,数据库查询特别慢。我第一反应是 SQL 写得烂,结果用 iostat 一看,磁盘利用率才 30%,但 await 高达 200 毫秒。嗯,这里要注意,不是磁盘满了才叫瓶颈,响应时间长了也是问题。
# 安装 sysstat 包(包含 iostat)
sudo apt install sysstat -y
# 每隔 2 秒输出一次,监控 sda 磁盘
iostat -x sda 2
2.4.1 核心指标
| 指标 | 含义 | 正常范围 |
|---|---|---|
| %util | 磁盘忙碌时间百分比 | < 80% 算正常 |
| await | IO 请求平均等待时间(ms) | SSD < 10ms,机械盘 < 50ms |
| svctm | IO 请求平均服务时间(ms) | 越接近 await 说明排队少 |
| r/s / w/s | 每秒读写次数 | SSD 通常能到几万次 |
避坑指南: 我曾经遇到一个案例,%util 只有 30%,但业务方说磁盘很慢。后来发现是磁盘做了 RAID 5,写操作有校验开销。所以看 iostat 不能只看 %util,要结合
await 和 svctm 一起看。
2.5 perf:CPU 热点函数的「显微镜」
前面几个工具都是「宏观」的,告诉你哪里有问题。但具体是哪一行代码导致的?这时候就要请出 perf 了。
# 采样 10 秒,记录 CPU 事件
sudo perf record -a -g -- sleep 10
# 生成火焰图数据
sudo perf script > out.perf
# 用 FlameGraph 工具生成 SVG 火焰图
git clone https://github.com/brendangregg/FlameGraph
cd FlameGraph
./stackcollapse-perf.pl ../out.perf > out.folded
./flamegraph.pl out.folded > flame.svg
2.5.1 perf 常用场景
- CPU 热点:
perf top实时查看当前 CPU 占用最高的函数 - 缓存 miss:
perf stat -e cache-misses ./your_app - 上下文切换:
perf stat -e context-switches ./your_app
实战案例: 我之前优化一个 Redis 集群,发现 CPU 使用率很高但 QPS 上不去。用 perf 采样后发现,热点函数是
dictFind,说明哈希冲突严重。调整了哈希表大小后,QPS 提升了 30%。
2.6 工具选择速查表
| 场景 | 首选工具 | 辅助工具 |
|---|---|---|
| CPU 跑满 | top / htop | perf(找热点函数) |
| 内存不足 | vmstat | free -m |
| 磁盘慢 | iostat -x | iotop(看哪个进程在读写) |
| 上下文切换高 | vmstat (cs 字段) | perf stat -e context-switches |
| 不知道哪里慢 | perf top | 火焰图 |
2.7 实战:一次完整的排查流程
最后,我带你走一遍真实场景。假设你的 Java 服务响应变慢了:
- 第一步:top 看全局
- 发现 CPU 使用率 90%,其中 %wa 占 40%
- 初步判断:磁盘 IO 可能是瓶颈
- 第二步:iostat 确认
iostat -x 1看到 %util 95%,await 150ms- 确认:磁盘确实扛不住了
- 第三步:vmstat 看内存
- 发现 si/so 不为 0,说明内存也在 swap
- 嗯,这里要注意,内存不足会导致磁盘 IO 增加
- 第四步:perf 定位代码
perf top -p <pid>看到热点在日志写入函数- 原来是日志框架配置了同步刷盘
- 第五步:优化
- 改成异步日志,加内存,问题解决
重要提醒: 性能排查最忌讳「猜」。不要觉得「可能是网络问题」就去调网络参数。先用工具看数据,让数据告诉你答案。我见过太多人凭感觉改配置,越改越糟。
好了,这一章的工具链你掌握了,以后遇到性能问题就不会慌了。记住那个排查顺序:top → vmstat → iostat → perf。从宏观到微观,从现象到本质。