火焰图怎么看

一、火焰图是什么?

火焰图是一种可视化 的性能分析工具,它展示了程序在采样期间CPU时间都花在了哪些函数上

你可以把它想象成一张"代码执行的热力图",越"热"(宽)的地方,就是消耗CPU最多的地方。


二、火焰图的核心构成

一张典型的火焰图(以CPU火焰图为例)通常包含以下要素:

  1. Y轴(纵向):调用栈深度

    • 每一层代表一个函数调用。
    • 最底层 是采样时正在执行的函数(通常是内核态的入口,如 [cpu_idle])。
    • 从下往上看,表示调用关系。上面的函数调用下面的函数。最顶层的函数是当前调用栈的"叶子节点"。
  2. X轴(横向):采样计数(CPU时间)

    • 注意:X轴不是时间顺序,而是按字母排序的! 这是为了把相同的函数合并在一起,方便查看。
    • 每个矩形的宽度 代表该函数在采样中出现的次数,或者说它消耗的CPU时间。越宽,表示该函数占用的CPU资源越多,越可能是性能瓶颈
  3. 每个矩形块代表一个函数

    • 矩形块上通常会标注函数名。
    • 颜色通常没有固定含义,只是为了区分不同函数,让图更易读。有时会用暖色调(如红色、黄色)来突出宽的部分。

三、如何解读火焰图:核心原则

看火焰图的核心思想是: "寻找最宽的平顶山"

平顶山(Flat Top) :当你看到一个函数的矩形块特别宽,并且它顶部没有或只有很少的其他调用(即它几乎是调用栈的顶部)时,这就形成了一个"平顶"。这个函数本身就是热点。

相反,如果一个很宽的函数上面还有很长的调用栈,说明是它调用的子函数消耗了大量时间,你应该顺着调用栈往上看,找到顶部的那个"叶子函数"。


四、实战分析:一步一步看

假设你拿到了一张火焰图,可以按照以下步骤进行分析:

第1步:忽略锯齿,寻找最宽的"平顶"

  • 不要被图上密密麻麻的"小火苗"干扰,你的目标是找到最宽的那一个或几个"火墙"。
  • 将目光锁定在最宽的矩形上。

第2步:从下往上阅读调用链

  • 找到最宽的矩形后,从它开始,从下往上看它的调用栈。

    • 例如:main() -> foo() -> bar() -> hotspot()
  • 这个调用链告诉你,是 main 函数调用了 foofoo 调用了 bar,最终 bar 调用了消耗CPU最多的 hotspot 函数。

第3步:定位问题根因

  • 情况A:平顶山

    • 如果 hotspot() 本身很宽,且顶部没有其他函数,那么 hotspot() 就是性能瓶颈。你需要优化这个函数本身的逻辑。
  • 情况B:深调用链

    • 如果 hotspot() 很宽,但它的顶部还有一个更宽的 slow_algo() 函数,那么真正的瓶颈是 slow_algo()。你需要优化的是 slow_algo 算法。

第4步:关注自身时间 vs 总时间

  • 总时间(矩形宽度) :一个函数及其所有子函数消耗的总时间。
  • 自身时间(Inclusive Time) :函数本身代码(不包括它调用的子函数)消耗的时间。
  • 在火焰图中,一个函数矩形的宽度是其"总时间" 。它的"自身时间"可以粗略地看作是它顶部没有其他函数的那部分宽度(即"平顶"的部分)。

因此,优化的首要目标是那些"自身时间"很长的函数(平顶山)。


五、一个简单的例子

假设下面是一个简化的调用栈,宽度代表CPU时间:

text

markdown 复制代码
[______ Baz ______] [_______ Qux _______]
[________________ Foo _________________] [__ Bar __]
  • 最宽的"墙"Foo

  • 阅读调用链Foo 调用了 BazQux

  • 分析

    • Foo 函数消耗了大量的CPU时间(总时间很长)。
    • 但是,Foo 的时间主要花在了它的两个子函数 BazQux 上。
    • QuxBaz 更宽,说明 Qux 是更大的热点。
    • 结论 :你应该优先去检查并优化 Qux 函数的实现。优化 Qux 将会直接减少 Foo 的总执行时间。

六、其他类型的火焰图

除了最常用的CPU火焰图,还有:

  • 内存火焰图:展示内存分配的热点。
  • Off-CPU火焰图:展示线程被阻塞(如I/O、锁、页错误)时的热点。
  • 差分火焰图:对比两个版本火焰图的差异,快速定位性能回归。

它们的看法和CPU火焰图大同小异,核心都是 Y轴看调用关系,X轴看资源消耗(宽度)

总结

  1. Y轴是调用栈,从下往上看。
  2. X轴是资源开销 ,越宽占比越大。X轴不是时间线!
  3. 核心口诀寻找最宽的平顶山
  4. 关键动作:找到最宽的矩形,然后从下往上阅读它的调用链,定位到最终需要优化的"叶子函数"。

多看几张图,亲手用 perfFlameGraph 脚本生成一次,你就会很快上手。火焰图是性能优化的"超级武器",掌握它会让你的调试能力大大提升。

相关推荐
Moonbit2 小时前
MoonBit Pearls Vol.12:初探 MoonBit 中的 Javascript 交互
javascript·后端·面试
摆烂工程师2 小时前
(2025年11月)开发了 ChatGPT 导出聊天记录的插件,ChatGPT Free、Plus、Business、Team 等用户都可用
前端·后端·程序员
gongzemin3 小时前
使用阿里云ECS部署前端应用
前端·vue.js·后端
用户8356290780513 小时前
使用Python合并Word文档:实现高效自动化办公
后端·python
小灰灰搞电子3 小时前
Rust Slint实现控件尺寸的扩展与收缩源码分享
开发语言·后端·rust
天天摸鱼的java工程师3 小时前
八年 Java 开发手敲:SpringBoot+SpringSecurity+JWT 实战,前后分离权限注解落地就能跑
java·后端
qianbailiulimeng3 小时前
IDEA + Spring Boot 的三种热加载方案
java·后端
王元_SmallA3 小时前
网卡驱动架构以及源码分析
java·后端
八苦3 小时前
实现 json path 来评估函数式解析器的损耗
后端