引言
大家好,今天我们来讲一下排查性能瓶颈、优化接口响应时间的"神兵利器" -- 火焰图。
那么火焰图是什么呢?简单来说,火焰图就是一种可视化堆栈轨迹(Stack Trace)的方式。它能让你一眼看出:程序的时间都花在哪个函数上了?接下来我们就详细讲一下怎么看火焰图等问题。
怎么看火焰图
我们首先一定要知道,函数的调用顺序其实就是栈的顺序,即最下面的就是第一个被调用的方法,如果你懂了栈的方法原理,那么接下来火焰图你也就可以轻松看懂。
很多新手第一次看火焰图会觉得头晕,其实只要记住两个维度和一个"宽度":
- Y 轴(纵向):代表调用栈的深度。 最底部是入口(比如
main或线程根),往上是不断调用的子函数。每一层都是它的下一层的子函数。 - X 轴(横向):并不代表时间先后顺序! 它是将所有的调用栈按照函数名进行字母排序后的结果。
- 宽度(最关键):代表该函数及其子函数在采样中出现的频率。 越宽,代表占用的资源(通常是 CPU 时间)越多。 如果一个函数的"平顶"很宽,说明这个函数本身(Self Time)逻辑很重,可能是性能瓶颈。
大白话总结: 哪块"火苗"最宽,哪块就是你需要优化的地方。
Java和Go生成火焰图
作为后端开发,你在不同语言环境下生成和分析火焰图的方式稍有不同:
Java 场景
在 Java 里,传统的采样(Sampling)容易遇到 Safepoint Bias(安全点偏差) 问题,导致结果不准。
-
推荐工具:
async-profiler(目前社区公认的标配)。 -
优势: 它通过 Linux 的
perf_events绕过了安全点问题,能同时看到 Java 代码、JVM 内部代码和系统库调用。 -
生成方式:
Bash./profiler.sh -d 30 -f output.html [PID]
Go 场景
Go 的工具链原生就非常强大,火焰图是"一等公民"。
-
推荐工具:
pprof。 -
使用方式: 在代码里引入
net/http/pprof,然后运行:Bashgo tool pprof -http=:8080 http://localhost:6060/debug/pprof/profile?seconds=30 -
优势: 浏览器直接打开,支持切换 CPU、内存(Heap)、协程(Goroutine)等多种维度的火焰图。
火焰图不止于CPU
虽然我们常用火焰图看 CPU 占用,但它其实可以分析任何采样数据:
- 内存火焰图(Alloc/Heap): 看看哪些路径在频繁申请内存,排查内存泄漏或 GC 压力。
- 差分火焰图(Differential): 优化了代码但不知道效果?对比"优化前"和"优化后"的两张图,它会用红色表示增加的部分,蓝色表示减少的部分。
- Off-CPU 火焰图: 这是高级货。如果 CPU 不忙但响应慢,可能是卡在 I/O、锁竞争或等待上了。这时候需要 Off-CPU 火焰图来观察线程在"睡觉"的时候都在等什么。
如何方便的生成火焰图
在我们平常用的IDE中,就拿Java的IDEA来说吧,他就能生成火焰图。
你不需要手动去命令行执行脚本,只需要以下几步:
-
找到 Profiler 入口: 在 IDEA 顶部运行栏,或者右键你的
main方法/单元测试。 -
选择性能分析模式: 点击那只"带小秒表的图标"(Run '...' with 'Profiler' )。
-
选择分析引擎:
- CPU Profiler (async-profiler): 推荐,最准,基于采样。
- Java Flight Recorder (JFR): Oracle 官方的黑匣子,适合全方位监控(线程、内存、锁)。
-
停止并查看: 运行一段时间后,点击 Stop Profiling ,IDEA 底部会自动弹出 Profiler 面板。
下面是seata的一个普通单测的火焰图:

为什么使用IDE来生成火焰图
我推荐本地开发和调优使用IDE来生成火焰图,生产环境使用命令行版 async-profiler。
比起浏览器里的静态 HTML 文件,IDEA 的火焰图是"活"的:
-
双向联动(Jump to Source): 这是最强大的功能。你在火焰图里看到哪个函数特别宽,直接右键 -> Jump to Source,它瞬间带你回到对应的 Java 类和行号。
-
实时搜索/高亮: 点击面板上的"放大镜",输入关键字(如
ArrayList或你的包名),所有相关的调用栈都会被高亮出来,帮你快速定位业务逻辑。 -
多维度切换: 在同一个面板里,你可以一键切换:
- Flame Graph: 传统的火焰图。
- Call Tree: 树状图,看具体的调用次数和百分比。
- Method List: 统计哪些方法最耗时(Top List)。
-
分析外部文件: 即使不是在 IDEA 里运行的程序(比如生产环境导出的
.jfr或.hprof文件),你也可以通过File -> Open或者Profiler面板的Import直接打开分析。
总结
我们平时遇到接口调用慢或者耗时长等问题,除了在对应面板看调用链之外,锁定具体目标分析时候使用火焰图则最为合适且直观,快去试试吧