2. 性能分析工具入门:Linux perf、top、htop、vmstat、iostat 等基础工具的使用
性能优化这件事,说白了就是先找到瓶颈在哪,再动手改代码。而找瓶颈,靠猜是不行的。我见过太多人一上来就盯着代码看,看了半天也不知道问题在哪。其实,Linux 自带的那些命令行工具,已经能告诉你 80% 的真相了。
这一章,咱们就把最常用的几个工具过一遍。你不用全记住,但得知道每个工具是干什么的,什么时候该用它。
2.1 top / htop:看一眼系统在忙什么
top 是我日常用得最多的命令。没有之一。每次登录服务器,第一件事就是敲 top,看看 CPU 和内存是不是正常。
核心用法:
# 直接运行
top
# 按 CPU 使用率排序(进入 top 后按 P)
# 按内存使用率排序(进入 top 后按 M)
# 查看每个 CPU 核心的负载(按 1)
你会看到一堆数字。别慌,重点看这几列:
- %CPU:进程占用的 CPU 百分比。如果某个进程一直占 100%,那它大概率是瓶颈。
- %MEM:内存占用。如果内存快满了,系统可能会开始用 swap,性能会急剧下降。
- load average:系统平均负载。三个数字分别代表 1 分钟、5 分钟、15 分钟的负载。如果这个值超过了 CPU 核心数,说明系统已经过载了。
我的习惯: 我一般先看 load average,如果它很高,再看是 CPU 还是 IO 导致的。怎么区分?如果 CPU 的 us(用户态)和 sy(系统态)加起来很高,那就是 CPU 瓶颈;如果 wa(等待 IO)很高,那就是磁盘或网络的问题。
htop 是 top 的增强版。它支持鼠标操作,颜色更友好,还能直接看到进程树。我个人更喜欢 htop,因为它可以横向滚动查看完整命令行,这在排查僵尸进程时特别有用。
# 安装 htop(如果系统没有)
sudo apt install htop # Debian/Ubuntu
sudo yum install htop # CentOS/RHEL
# 运行
htop
2.2 vmstat:系统整体健康检查
vmstat 是我用来做快速健康检查的工具。它不像 top 那样盯着进程看,而是告诉你整个系统的运行状况。
# 每隔 1 秒输出一次,共输出 5 次
vmstat 1 5
输出结果里,我重点关注这几列:
| 列名 | 含义 | 警戒线 |
|---|---|---|
| r | 正在运行和等待 CPU 的进程数 | 如果持续大于 CPU 核心数,说明 CPU 不够用 |
| b | 不可中断睡眠的进程数(通常是在等 IO) | 如果持续大于 0,说明 IO 有问题 |
| si / so | 从磁盘交换进/出的内存量 | 如果持续大于 0,说明内存不足 |
| us / sy / id / wa | CPU 时间分配:用户态、系统态、空闲、等待 IO | wa 高 -> 磁盘慢;sy 高 -> 系统调用频繁 |
我曾经踩过的坑: 有一次线上服务响应变慢,我看 top 发现 CPU 使用率不高,但 vmstat 的 b 列一直大于 0。排查了半天,才发现是磁盘在做全量备份,导致 IO 阻塞。如果当时只看 top,可能还要多花两个小时。
2.3 iostat:磁盘到底有多慢
当 vmstat 告诉你 wa 很高时,就该用 iostat 来深挖磁盘问题了。
# 安装 sysstat 包(iostat 包含在其中)
sudo apt install sysstat
# 每隔 2 秒输出一次磁盘统计
iostat -x 2
输出里,我最关心的指标是:
- %util:磁盘忙闲程度。如果接近 100%,说明磁盘已经满负荷了。
- await:IO 请求的平均等待时间(毫秒)。SSD 一般应该在 1ms 以内,机械盘在 10ms 以内算正常。如果超过 100ms,那基本可以断定磁盘是瓶颈。
- svctm:IO 服务的实际时间。如果这个值远小于
await,说明请求在排队,磁盘队列太长了。
一个小技巧: 如果你看到 %util 很高但 await 很低,那可能是磁盘本身很快(比如 NVMe SSD),但请求量太大。这时候可以考虑优化应用层的 IO 模式,比如合并小写入、使用异步 IO。
2.4 perf:性能分析的瑞士军刀
perf 是 Linux 内核自带的性能剖析工具。它不像 top 那样只看表面,而是能深入到 CPU 的硬件计数器层面,告诉你代码到底慢在哪一行。
说实话,perf 的学习曲线有点陡。但掌握几个常用命令,就能解决大部分问题。
2.4.1 采样分析(最常用)
# 对正在运行的进程进行采样,持续 10 秒
perf record -p PID -g -- sleep 10
# 查看采样结果
perf report
-g 参数会记录调用栈。这样你就能看到,CPU 时间到底花在了哪个函数里,以及是谁调用了它。
我的经验: 有一次一个 Java 应用 CPU 飙升到 300%。用 perf top 一看,发现热点全在 java.lang.String.indexOf 里。顺着调用栈找到代码,发现是一个循环里在用 indexOf 做字符串匹配。改成 HashMap 后,CPU 直接降到了 50%。
2.4.2 实时热点查看
# 实时显示 CPU 热点(类似 top,但按函数名聚合)
perf top
这个命令特别适合快速定位「谁在吃 CPU」。你不需要停服务,也不需要改代码,直接就能看到最热的函数。
2.4.3 统计缓存命中率
# 统计 LLC(最后一级缓存)的命中率
perf stat -e cache-misses,cache-references -p PID
如果缓存缺失率很高,说明你的数据访问模式对 CPU 缓存不友好。这时候可以考虑调整数据结构,或者做数据对齐。
2.5 工具选择:什么时候用哪个?
这么多工具,不可能每次都用一遍。我一般按这个思路来:
- 先看整体:
top或htop,看看 CPU、内存、负载是否正常。 - 再查系统:
vmstat,确认瓶颈是 CPU、内存还是 IO。 - 深挖磁盘:如果
vmstat显示 IO 有问题,用iostat -x看磁盘细节。 - 定位代码:如果 CPU 高,用
perf top或perf record找到热点函数。
下面这张图,是我自己总结的排查流程,你可以参考一下:
2.6 实战案例:一次 CPU 飙升的排查
光说不练假把式。我拿一个真实案例来串一遍这些工具。
现象: 线上服务响应变慢,用户反馈请求超时。
排查过程:
- 登录服务器,敲
top:看到 load average 是 12.5,而服务器只有 4 核 CPU。明显过载了。 - 按 P 排序:发现一个 Java 进程占用了 350% 的 CPU(4 核占满 3.5 核)。
- 跑
vmstat 1 5:r列一直在 10 以上,wa接近 0。确认是 CPU 瓶颈,不是 IO。 - 用
perf top -p PID:看到热点函数是com.example.service.calculate(),占 CPU 的 60%。 - 用
perf record -p PID -g -- sleep 30采样:生成报告后,发现calculate()里有一个循环,每次都在做大量的BigDecimal除法运算。 - 优化:把
BigDecimal除法换成预计算好的查表法。上线后,CPU 降到 80%,负载恢复正常。
复盘: 如果当时没有 perf,我可能还在用 top 盯着进程看,或者盲目加机器。而 perf 直接告诉我问题出在哪个函数,省去了大量猜测的时间。
2.7 小结
这一章的工具,都是 Linux 性能分析的「基本功」。你不用每个都精通,但至少要知道:
top/htop看全局vmstat判断瓶颈类型iostat深挖磁盘perf定位代码热点
把这些工具练熟了,遇到性能问题,你就能像老中医一样——望闻问切,对症下药。