译文:解读火焰图
要想解读一张火焰图(FlameGraph),最好的方法就是理解它是如何生成的。
待分析的示例应用
以如下伪代码程序为例:
main() {
// 某种业务逻辑
func3() {
// 某种业务逻辑
func7();
}
// 某种业务逻辑
func4();
// 某种业务逻辑
func1() {
// 某种业务逻辑
func5();
}
// 某种业务逻辑
func2() {
// 某种业务逻辑
func6() {
// 某种业务逻辑
func8(); // 此处是 CPU 密集型的处理逻辑
}
}
分析器采样
所谓分析(profiling)即是每秒做 X 次采样。采样时会将当时的调用栈保存下来。下图显示的是未经排序聚合的采样视图。
如下是对应的采样次数:
func3()->func7():3次采样func4():1次采样func1()->func5():2次采样func2()->func8():4次采样func2()->func6():1次采样
对样本进行排序
接着,对样本从应用程序的起始点(或主方法)开始按照字母序排序。
请注意:X 轴不再是时间线。火焰图不会保留特定栈追踪(stack trace)发生时的时间信息,它仅表示在分析过程中该栈追踪被观察到的频率。
聚合视图
然后,将每个栈深度层级上相同函数的表示块拼接在一起,从而获得火焰图的聚合视图。
这个例子中,和 func4() 同一层级的其他函数都没有实际消耗资源(除了 func4())。func5()、func6()、func7()和func8()均消耗了一定的资源,func8()应该是性能优化的优选对象。
CPU 使用率(CPU utilization)是火焰图最常见的使用场景,不过还有其他类型的分析,比如:内存分配分析(allocation profiling) - 用于查看堆内存使用情况,墙上时钟分析(wall-clock profiling) - 用于查看延迟情况。
理解火焰图颜色
颜色是火焰图中用于编码每个栈帧附加信息的另一个维度。不同的火焰图实现中,颜色可能有不同的含义。async-profiler 使用以下调色板来区分栈帧类型: