原文:FlameGraph interpretation

要想解读一张火焰图(FlameGraph),最好的方法就是理解它是如何生成的。

待分析的示例应用

以如下伪代码程序为例:

main() {
     // 某种业务逻辑
    func3() {
        // 某种业务逻辑
        func7();
    }

    // 某种业务逻辑
    func4();

    // 某种业务逻辑
    func1() {
        // 某种业务逻辑
        func5();
    }

    // 某种业务逻辑
    func2() {
        // 某种业务逻辑
        func6() {
            // 某种业务逻辑
            func8(); // 此处是 CPU 密集型的处理逻辑
    }
}

分析器采样

所谓分析(profiling)即是每秒做 X 次采样。采样时会将当时的调用栈保存下来。下图显示的是未经排序聚合的采样视图。

ProfilerSamplings.png

如下是对应的采样次数:

  • func3()->func7():3次采样
  • func4():1次采样
  • func1()->func5():2次采样
  • func2()->func8():4次采样
  • func2()->func6():1次采样

对样本进行排序

接着,对样本从应用程序的起始点(或主方法)开始按照字母序排序。

SortedSamplings.png

请注意:X 轴不再是时间线。火焰图不会保留特定栈追踪(stack trace)发生时的时间信息,它仅表示在分析过程中该栈追踪被观察到的频率。

聚合视图

然后,将每个栈深度层级上相同函数的表示块拼接在一起,从而获得火焰图的聚合视图。

AggregatedView.png

这个例子中,和 func4() 同一层级的其他函数都没有实际消耗资源(除了 func4())。func5()func6()func7()func8()均消耗了一定的资源,func8()应该是性能优化的优选对象。

CPU 使用率(CPU utilization)是火焰图最常见的使用场景,不过还有其他类型的分析,比如:内存分配分析(allocation profiling) - 用于查看堆内存使用情况,墙上时钟分析(wall-clock profiling) - 用于查看延迟情况。

若想了解更多关于各种分析模式的信息,请阅读这里

理解火焰图颜色

颜色是火焰图中用于编码每个栈帧附加信息的另一个维度。不同的火焰图实现中,颜色可能有不同的含义。async-profiler 使用以下调色板来区分栈帧类型:

flamegraph_colors.png