3. 性能剖析工具概览:Linux性能工具、Java性能工具、Python性能工具、前端性能工具

说实话,性能优化这件事,工具选对了,你就成功了一半。我见过太多人一上来就对着代码瞎猜,结果折腾半天连瓶颈在哪都没摸到。你想想看,没有温度计你怎么知道发烧了?没有听诊器你怎么知道肺里有痰?性能工具就是我们的温度计和听诊器。

这一章,我会带你快速过一遍四个领域的常用工具。别指望一口气全记住,先混个脸熟,知道什么场景该用什么工具就行。我在项目中踩过的坑,也会一并告诉你。

3.1 Linux 性能工具:系统级排查的基石

不管你的应用是用 Java、Python 还是 Go 写的,最终都跑在 Linux 上。所以,Linux 性能工具是基本功。我个人习惯把这套工具分成两类:「看全局的」和「查细节的」。

3.1.1 全局视角:top、htop、vmstat

top 命令,老牌工具了。一上来先看 load average,三个数字分别代表 1 分钟、5 分钟、15 分钟的平均负载。如果 1 分钟远高于 15 分钟,说明系统正在经历突发压力。

我建议你装个 htop,它是 top 的增强版。颜色更友好,还能用鼠标操作。嗯,这里要注意:htop 默认不显示线程,你得按 H 键切换。

核心指标速查:
  • %us:用户态 CPU 占用。高的话说明应用在算东西。
  • %sy:内核态 CPU 占用。高的话说明系统调用频繁,或者有锁竞争。
  • %wa:等待 I/O 的时间。高的话说明磁盘或网络是瓶颈。
  • %st:被虚拟机偷走的时间。云服务器上常见,说明宿主机超卖了。

vmstat 1 是我最常用的实时监控命令。每隔 1 秒输出一次。重点关注 r(运行队列)、b(阻塞队列)、si/so(交换分区读写)。

# 每秒输出一次,共输出 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 123456  1024 2048576    0    0    10    20  500  800 12  3 85  0  0

我曾经遇到过一个案例,r 队列一直大于 CPU 核数,但 CPU 空闲率却很高。排查了半天,发现是某个进程在疯狂触发缺页中断,导致上下文切换爆炸。这就是 cs(context switch)列飙到几万的原因。

3.1.2 磁盘与网络:iostat、sar、netstat

iostat -x 1 可以看磁盘的详细情况。重点关注 %util 和 await。%util 接近 100% 说明磁盘已经饱和了。await 是 I/O 请求的平均等待时间,SSD 一般应该在 1ms 以内。

避坑指南:我曾经被 %util 骗过一次。某个 SSD 的 %util 只有 30%,但应用已经慢得不行了。后来发现是 await 高达 200ms,说明磁盘内部在做垃圾回收。所以,别只看一个指标。

sar 是个历史数据收集器。默认系统会每 10 分钟记录一次性能数据。你可以用 sar -u -f /var/log/sa/saXX 回溯昨天的 CPU 使用情况。这在排查「昨晚到底发生了什么」时特别好用。

网络方面,netstat -s 可以看协议栈的统计信息。比如 retransmitted 段数,如果这个值很高,说明网络丢包严重。

3.1.3 进程级诊断:strace、lsof、perf

strace -p PID 可以跟踪进程的系统调用。这是终极武器,但也是双刃剑。因为它会大幅降低进程性能,生产环境慎用。

我一般这样用:先 strace -c -p PID 统计系统调用的次数和耗时,找到最耗时的系统调用后,再用 strace -e trace=xxx -p PID 定向跟踪。

# 统计系统调用
strace -c -p 12345

# 只跟踪 read 和 write 调用
strace -e trace=read,write -p 12345

lsof 可以看进程打开了哪些文件。排查「too many open files」错误时必备。perf 是 Linux 内核自带的性能剖析工具,可以采样 CPU 的调用栈,定位热点函数。

我的经验:perf 的 perf top 命令可以实时显示 CPU 热点。如果某个函数占用了 30% 以上的 CPU,那基本就是优化目标了。

3.2 Java 性能工具:JVM 内部的探针

Java 应用有 JVM 这层虚拟机,所以工具也分两层:JVM 层和应用层。

3.2.1 JDK 自带工具:jstack、jmap、jstat、jcmd

这些工具都在 JDK 的 bin 目录下。我个人最常用的是 jstat,它可以实时监控 GC 情况。

# 查看 GC 统计,每 1 秒输出一次
jstat -gcutil PID 1000

# 输出示例
 S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
 0.00   0.00  45.23  78.12  92.34  88.56   1234   12.345     5    0.678   13.023

jstack 可以打印线程堆栈。当 CPU 飙高时,用 jstack PID | grep -A 30 "RUNNABLE" 找到正在运行的线程,看看它在执行什么代码。

jmap -heap PID 可以查看堆内存的配置和使用情况。jmap -histo PID 可以列出所有对象的数量和占用内存,帮你找到内存泄漏的嫌疑对象。

实战技巧:当应用卡死时,先 jstack PID 连续 dump 三次,每次间隔 5 秒。然后对比三个 dump 文件,看哪些线程一直卡在同一个地方。那就是死锁或者长时间等待的线索。

3.2.2 可视化工具:VisualVM、JMC、Arthas

VisualVM 是 Oracle 官方提供的图形化工具。可以看 CPU、内存、线程、GC 的实时曲线。我习惯用它来观察 GC 的频率和耗时,如果 Full GC 频繁,那就要调堆内存大小了。

JMC(Java Mission Control) 是 Oracle 的商业工具,现在对 JDK 11+ 免费了。它的 飞行记录器(JFR) 功能可以在低开销下持续记录 JVM 的运行数据。生产环境也能用。

Arthas 是阿里巴巴开源的诊断工具。我最喜欢它的 watch 命令,可以实时查看某个方法的入参、返回值、异常,甚至还能动态修改代码逻辑。嗯,这个工具我强烈建议你装一个。

# 监控 com.example.service.UserService.getUser 方法
watch com.example.service.UserService getUser '{params, returnObj}' -x 2

3.3 Python 性能工具:从脚本到服务

Python 的性能工具相对轻量,但够用。我把它分成内置模块和第三方工具两类。

3.3.1 内置模块:timeit、cProfile、trace

timeit 适合微基准测试。比如你想比较列表推导式和 for 循环哪个快,用 timeit 一测便知。

import timeit

# 测试列表推导式
timeit.timeit('[x**2 for x in range(1000)]', number=10000)

# 测试 for 循环
timeit.timeit('''
result = []
for x in range(1000):
    result.append(x**2)
''', number=10000)

cProfile 是 Python 自带的性能剖析器。它会记录每个函数的调用次数和耗时。我一般这样用:

python -m cProfile -o output.prof my_script.py

然后用 pstats 模块分析结果,或者用 snakeviz 生成火焰图。

我的习惯:先用 cProfile 跑一次,找到最耗时的函数。然后针对那个函数,用 timeit 做微优化。这样效率最高。

3.3.2 第三方工具:py-spy、memory_profiler、line_profiler

py-spy 是一个采样剖析器,不需要修改代码,直接 attach 到运行中的进程。它支持生成火焰图,对排查 CPU 热点非常有用。

# 对运行中的进程进行采样
py-spy record -o flamegraph.svg --pid 12345

# 或者直接查看实时调用栈
py-spy top --pid 12345

memory_profiler 可以逐行分析内存使用。用 @profile 装饰器标记要分析的函数,然后运行 python -m memory_profiler my_script.py。

line_profiler 可以逐行分析代码的执行时间。它比 cProfile 更细粒度,能精确到每一行代码。

3.4 前端性能工具:浏览器端的显微镜

前端性能优化,说白了就是让页面加载更快、交互更流畅。工具主要集中在浏览器开发者工具和性能审计工具。

3.4.1 Chrome DevTools:Performance、Network、Lighthouse

Performance 面板是前端性能分析的核心。点击录制按钮,然后操作页面,结束后会生成一个时间线。重点关注:

  • FPS:帧率。低于 30 说明有卡顿。
  • CPU 火焰图:看哪些函数占用了大量 CPU。
  • Layout / Paint:布局和绘制事件。频繁触发说明有强制回流。

Network 面板可以看每个请求的耗时。重点关注 TTFB(Time To First Byte),如果这个值超过 200ms,说明后端响应慢。另外,瀑布图里如果有大量请求串行加载,说明有资源依赖没处理好。

Lighthouse 是 Google 的自动化审计工具。它会生成一个性能报告,给出具体的优化建议。比如「图片太大,建议压缩」或者「未使用懒加载」。

核心指标:
指标 含义 目标值
FCP 首次内容绘制 < 1.8s
LCP 最大内容绘制 < 2.5s
FID 首次输入延迟 < 100ms
CLS 累计布局偏移 < 0.1

3.4.2 其他工具:WebPageTest、Bundle Analyzer

WebPageTest 是一个在线工具,可以从全球多个节点测试你的页面加载速度。它比 Lighthouse 更详细,能模拟 3G 网络、慢速 CPU 等场景。

Bundle Analyzer 用于分析打包后的 JavaScript 文件。如果你用 Webpack,可以配置 webpack-bundle-analyzer 插件,生成一个交互式的树状图,直观地看到哪些模块占用了大量体积。

避坑指南:我曾经遇到一个项目,打包后的 JS 文件有 5MB。用 Bundle Analyzer 一看,发现某个第三方库被重复打包了 3 次。原因是不同模块引用了不同版本的同一个库。解决办法是用 Webpack 的 resolve.alias 统一版本。

3.5 知识体系总览

下面这张图,是我自己总结的性能工具知识体系。你可以把它当作一个「工具地图」,遇到问题先看属于哪个领域,再去找对应的工具。

性能剖析工具 Linux 性能工具 top / htop / vmstat iostat / sar / netstat strace / lsof / perf Java 性能工具 jstack / jmap / jstat VisualVM / JMC Arthas Python 性能工具 timeit / cProfile py-spy memory_profiler 前端性能工具 Chrome DevTools Lighthouse WebPageTest 核心思路:先全局后局部,先系统后应用,先工具后代码

最后说一句:工具是死的,人是活的。别为了用工具而用工具。我见过有人把 strace 挂在生产环境上跑了半小时,结果把数据库连接池打爆了。嗯,那就是反面教材。

记住一个原则:先问「我要解决什么问题」,再选「用什么工具」。这样你才不会在工具的海洋里迷失方向。

可可精品资料库