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 工具选择:什么时候用哪个?

这么多工具,不可能每次都用一遍。我一般按这个思路来:

  1. 先看整体:top 或 htop,看看 CPU、内存、负载是否正常。
  2. 再查系统:vmstat,确认瓶颈是 CPU、内存还是 IO。
  3. 深挖磁盘:如果 vmstat 显示 IO 有问题,用 iostat -x 看磁盘细节。
  4. 定位代码:如果 CPU 高,用 perf top 或 perf record 找到热点函数。

下面这张图,是我自己总结的排查流程,你可以参考一下:

性能分析工具选择流程图 性能分析工具选择流程 发现性能问题 第一步:top / htop(看整体负载) 第二步:vmstat(定位瓶颈类型) 瓶颈是 CPU 还是 IO? CPU 高 → perf top IO 高 → iostat -x perf record 定位热点函数 分析 IO 模式,优化读写 提示:先看整体,再定位具体瓶颈,最后用 perf 或 iostat 深挖细节

2.6 实战案例:一次 CPU 飙升的排查

光说不练假把式。我拿一个真实案例来串一遍这些工具。

现象: 线上服务响应变慢,用户反馈请求超时。

排查过程:

  1. 登录服务器,敲 top:看到 load average 是 12.5,而服务器只有 4 核 CPU。明显过载了。
  2. 按 P 排序:发现一个 Java 进程占用了 350% 的 CPU(4 核占满 3.5 核)。
  3. 跑 vmstat 1 5:r 列一直在 10 以上,wa 接近 0。确认是 CPU 瓶颈,不是 IO。
  4. 用 perf top -p PID:看到热点函数是 com.example.service.calculate(),占 CPU 的 60%。
  5. 用 perf record -p PID -g -- sleep 30 采样:生成报告后,发现 calculate() 里有一个循环,每次都在做大量的 BigDecimal 除法运算。
  6. 优化:把 BigDecimal 除法换成预计算好的查表法。上线后,CPU 降到 80%,负载恢复正常。

复盘: 如果当时没有 perf,我可能还在用 top 盯着进程看,或者盲目加机器。而 perf 直接告诉我问题出在哪个函数,省去了大量猜测的时间。

2.7 小结

这一章的工具,都是 Linux 性能分析的「基本功」。你不用每个都精通,但至少要知道:

  • top/htop 看全局
  • vmstat 判断瓶颈类型
  • iostat 深挖磁盘
  • perf 定位代码热点

把这些工具练熟了,遇到性能问题,你就能像老中医一样——望闻问切,对症下药。