火焰图

Cloud Profiler 使用火焰图显示性能剖析数据。与树和图表不同,火焰图通过紧凑、可读的格式表示大量信息,有效地利用屏幕空间。

为了介绍火焰图,本页面演示了如何将树转换为火焰图,并总结了火焰图的主要特点。

创建火焰图

如需根据树来创建火焰图,请完成下图中所示的步骤:

创建火焰图。

  1. 从树中移除指示函数调用的箭头。

  2. 用帧替换每个树节点。

    帧的形状为矩形,所有帧的高度相同。 对于本页面中的示例,帧中指明的函数使用的总计 CPU 时间决定了帧的宽度。

    每个函数的伪代码如下表所述。在函数执行期间执行的 CPU 密集型工作定义了自身 CPU 时间:

    函数伪代码 自身 CPU 时间
    (秒)
    总计 CPU 时间
    (秒)
    func main():
         foo1()
         foo2()
         // CPU intensive work
         // for 2 seconds 
    2 4 + 3 + 2 = 9
    func foo1():
         bar()
         // CPU intensive work
         // for 1.5 seconds 
    1.5 2.5 + 1.5 = 4
    func foo2():
         bar()
         // CPU intensive work
         // for 0.5 seconds 
    0.5 2.5 + 0.5 = 3
    func bar():
         // CPU intensive work
         // for 2.5 seconds
    2.5 2.5

  3. 下一步是移除帧之间的垂直空白,并将帧向左边对齐,同时保持调用序列。 (可选)您可以定义一个配色方案,并根据定义为帧着色。 例如,您可以按照软件包、总计 CPU 时间、自身 CPU 时间或其他计量单位对帧进行着色。

    移除多余的空白并按照自身 CPU 时间对帧着色后,火焰图现在如下所示:

    火焰图的详细图示。

    请注意,foo1foo2 的调用堆栈已保留,即使以 foo2 开头的调用堆栈现位于 foo1 的帧旁边。

总结

这个简单的示例说明了以下几个方面:

  • 火焰图是树的紧凑表示形式,通过从顶部向下跟踪帧,您可以重新创建调用堆栈。
  • 帧指明一个函数,帧的宽度是该函数的总计 CPU 时间的相对大小。 在本示例中,因为 foo2 的总计 CPU 时间是 main 的总计 CPU 时间的三分之一,所以 foo2 的帧宽度是 main 的帧宽度的三分之一。
  • 帧下方的空白区域的宽度是帧中指明函数的自身 CPU 时间的相对大小。 例如,在帧 foo1 下方,1.5 个单位为空,2.5 个单位被 bar 占用。因此,foo1 的自身 CPU 时间是其总 CPU 时间的 37.5%,即 1.5 秒。
  • 当您跟踪调用堆栈时,帧的宽度会减小,因为被调用者的总计 CPU 时间不可能超过调用者的总计 CPU 时间。这种行为是形成火焰形状的原因。

    在本示例中,foo1 调用 barfoo1 的总计 CPU 时间定义为 bar 的总计 CPU 时间加上 foo1 的自身 CPU 时间。因此,bar 的总计 CPU 时间不可能超过 foo1 的总计 CPU 时间。

后续步骤