下载本文的PDF版本 PDF

火焰图

这种软件执行可视化是性能分析和调试的一项新需求。


Brendan Gregg,Netflix

我们行业中一个常见的问题是理解软件如何消耗资源,特别是CPU。究竟是什么在消耗多少资源?自上次软件版本以来,情况发生了怎样的变化?这些问题可以通过软件性能分析器来解答,这些工具可以帮助引导开发人员优化其代码,并帮助运维人员调整其环境。然而,性能分析器的输出可能非常冗长,使得研究和理解起来很费力。火焰图为性能分析器输出提供了一种新的可视化方式,可以大大加快理解速度,从而缩短根本原因分析的时间。

在软件快速迭代的环境中,例如 Netflix 云微服务架构,快速理解性能分析结果尤为重要。更快的理解速度还可以使对外部软件的研究更加成功,因为在这些情况下,人们的技能、兴趣和时间都受到严格限制。

火焰图可以从许多不同的软件性能分析器的输出中生成,包括针对不同资源和事件类型的性能分析。本文从 CPU 性能分析入手,介绍火焰图的工作原理,然后探讨导致其产生的实际问题。

CPU 性能分析

一种常见的 CPU 性能分析技术是对堆栈跟踪进行采样,这可以使用 Linux perf_events 和 DTrace 等性能分析器来执行。堆栈跟踪是显示代码路径沿袭的功能调用列表。例如,以下堆栈跟踪将每个函数显示为一行,并且自上而下的顺序是从子级到父级:


SpinPause
StealTask::do_it
GCTaskThread::run
java_start
start_thread

考虑到采样开销、配置文件大小和应用程序变化等因素的平衡,一个典型的 CPU 配置文件可能会以以下方式收集:以每秒 99 次(而不是 100 次,以避免锁步采样)的速率对所有 CPU 进行 30 秒的堆栈跟踪采样。对于一个 16 核 CPU 系统,生成的配置文件将包含 47,520 个堆栈跟踪样本。作为文本,这将是数十万行。

幸运的是,性能分析器有方法来压缩其输出。例如,DTrace 可以测量和打印唯一的堆栈跟踪,以及它们的出现次数。这种方法比听起来更有效:相同的堆栈跟踪可能会在循环期间或当 CPU 处于空闲状态时重复出现。这些会被压缩成一个带有计数的单个堆栈跟踪。

Linux perf_events 可以进一步压缩性能分析器输出:不仅可以合并相同的堆栈跟踪样本,还可以合并堆栈跟踪的子集。这以树状视图呈现,其中每个代码路径分支都有计数或百分比,如图 1 所示。

The Flame Graph

在实践中,来自 DTrace 或 perf_events 的输出摘要足以在许多情况下解决问题,但也有些情况下,输出会产生大量的文本,使得理解大部分配置文件变得困难或不切实际。

问题

导致火焰图创建的问题是 Joyent 公有云3上的应用程序性能。该应用程序是一个 MySQL 数据库,其 CPU 资源消耗比预期多出约 40%。

DTrace 被用来以 997 Hz 的频率对应用程序的用户模式堆栈跟踪进行 60 秒的采样。即使 DTrace 只打印了唯一的堆栈跟踪,输出也长达 591,622 行,其中包括 27,053 个唯一的堆栈跟踪。幸运的是,最后一屏——其中包括最常采样的堆栈跟踪——看起来很有希望,如图 2 所示。

The Flame Graph

最频繁的堆栈跟踪包括一个 MySQL calc_sum_of_all_status() 函数,表明它正在处理一个“show status”命令。也许客户启用了积极的监控,这解释了较高的 CPU 使用率?

为了量化这一理论,将堆栈跟踪计数 (5,530) 除以捕获的配置文件中的总样本数 (348,427),表明它仅占 CPU 时间的 1.6%。仅凭这一点无法解释较高的 CPU 使用率。有必要了解更多配置文件信息。

浏览更多堆栈跟踪变成了一种收益递减的练习,因为它们从最频繁到最不频繁的顺序进行。问题的规模在图 3 中显而易见,其中整个 DTrace 输出变成了一个没有特征的灰色方块。

The Flame Graph

面对如此多的输出需要研究,在合理的时间范围内解决这个问题开始让人感到难以克服。必须有一种更好的方法。

我创建了一个可视化的原型,它利用堆栈跟踪的层次结构来组合公共路径。结果如图 4 所示,它可视化了与图 3 相同的输出。由于可视化解释了 CPU 为何“发热”(繁忙),我认为选择暖色调是合适的。凭借温暖的颜色和火焰状的形状,这些可视化被称为火焰图。(图 4 的交互式 SVG [可缩放矢量图形] 格式版本可在 https://queue.org.cn/downloads/2016/Gregg4.svg 获取。)

The Flame Graph

火焰图使得可以非常快速地理解配置文件的主要部分。它表明,早期的线索,MySQL status 命令,在所有堆栈组合在一起时仅占配置文件的 3.28%。大部分 CPU 时间消耗在 MySQL join 中,这为真正的问题提供了线索。问题被定位并修复,CPU 使用率降低了 40%。

火焰图详解

火焰图可视化了一组堆栈跟踪(也称为调用堆栈),以邻接图的形式显示,采用倒置的冰柱布局7。火焰图通常用于可视化 CPU 性能分析器的输出,其中堆栈跟踪使用采样收集。

火焰图具有以下特征:

• 堆栈跟踪表示为一列框,其中每个框代表一个函数(一个堆栈帧)。

• y 轴显示堆栈深度,从底部的根到顶部的叶进行排序。顶部框显示收集堆栈跟踪时正在 CPU 上运行的函数,而其下方的所有内容都是它的沿袭。函数下方的函数是它的父函数。

• x 轴跨越堆栈跟踪集合。它显示时间的流逝,因此从左到右的顺序没有特殊含义。堆栈跟踪从左到右的顺序是根据函数名称按字母顺序排列的,从每个堆栈的根到叶。这最大化了框的合并:当相同的函数框水平相邻时,它们会被合并。

• 每个函数框的宽度显示了该函数在堆栈跟踪中出现的频率,或者是堆栈跟踪沿袭的一部分。宽度较大的函数框比宽度较小的函数框在堆栈跟踪中出现得更频繁,与其宽度成正比。

• 如果框的宽度足够,它会显示完整的函数名称。如果不够,则会显示带有省略号的截断函数名称,或者什么也不显示。

• 每个框的背景颜色并不重要,而是随机选择的暖色调。这种随机性有助于眼睛区分框,特别是对于相邻的细“塔”。稍后将讨论其他配色方案。

• 可视化的配置文件可能跨越单个线程、多个线程、多个应用程序或多个主机。如果需要,可以生成单独的火焰图,特别是用于研究单个线程。

• 堆栈跟踪可以从不同的性能分析器目标收集,宽度可以反映样本计数以外的度量。例如,性能分析器(或跟踪器)可以测量线程被阻塞的时间,以及它的堆栈跟踪。这可以可视化为火焰图,其中 x 轴跨越总阻塞时间,而火焰图显示阻塞代码路径。

由于整个性能分析器输出一次性可视化,最终用户可以直观地导航到感兴趣的区域。火焰图中的形状和位置成为软件执行的可视化地图。

虽然火焰图使用交互性来提供额外的功能,但这些特征可以通过静态火焰图来实现,静态火焰图可以作为图像共享(例如,PNG 文件或打印在纸上)。虽然只有宽框有足够的空间来包含函数标签文本,但它们也足以显示配置文件的主要部分。

交互性

火焰图可以支持交互式功能,以显示更多细节、改进导航和执行计算。

火焰图的原始实现4创建了一个带有嵌入式 JavaScript 的 SVG 图像以实现交互性,然后在浏览器中加载。它支持三个交互式功能:鼠标悬停显示信息、点击缩放和搜索。

鼠标悬停显示信息

当鼠标悬停在框上时,火焰图下方的提示行和工具提示会显示完整的函数名称、配置文件中存在的样本数量以及这些样本在配置文件中对应的百分比。例如,Function: mysqld'JOIN::exec(272,959 个样本,78.34%)。

这对于从未标记的框中显示函数名称很有用。百分比还可以量化配置文件中的代码路径,这有助于用户确定优先线索并估算建议更改带来的改进。

点击缩放

当单击一个框时,火焰图会水平缩放。这会显示更多细节,通常是子函数的函数名称。单击框下方的祖先帧会以淡化的背景显示,作为视觉提示,表明它们的宽度现在仅部分显示。包含一个“重置缩放”按钮以返回到原始的完整配置文件视图。在缩放时单击任何框将重置缩放到关注该新框。

搜索

搜索按钮或快捷键 (Ctrl-F) 会提示用户输入搜索词,其中可以包括正则表达式。搜索配置文件中的所有函数名称,任何匹配的框都会以洋红色背景突出显示。匹配的堆栈跟踪的总和也显示在火焰图上,作为占总配置文件的百分比,如图 5 所示。(图 5 的交互式 SVG 格式版本可在 https://queue.org.cn/downloads/2016/Gregg5.svg 获取。)

The Flame Graph

这不仅对于定位函数很有用,而且对于突出显示函数的逻辑分组也很有用——例如,搜索 "^ext4_" 以查找 Linux ext4 函数。

对于某些火焰图,许多不同的代码路径可能以感兴趣的函数结尾——例如,自旋锁函数。如果这出现在 20 个或更多位置,则计算它们对配置文件的总贡献将是一项繁琐的任务,涉及查找然后添加每个百分比。搜索功能使这变得微不足道,因为总百分比会被计算出来并显示在屏幕上。

说明

到目前为止,已经有几种火焰图的实现5。原始实现 FlameGraph4是用 Perl 编程语言编写的,并以开源形式发布。它使火焰图的生成成为一个三步序列,包括使用性能分析器:

1. 使用性能分析器收集堆栈跟踪(例如,Linux perf_events、DTrace、Xperf)。

2. 将性能分析器输出转换为“折叠”的中间格式。FlameGraph 软件附带了各种程序来处理不同的性能分析器;它们的程序名称以“stackcollapse”开头。

3. 使用 flamegraph.pl 生成火焰图。这会读取之前的折叠格式,并将其转换为带有嵌入式 JavaScript 的 SVG 火焰图。

折叠堆栈跟踪格式将堆栈跟踪放在单行上,函数之间用分号分隔,后跟一个空格,然后再跟一个计数。应用程序的名称,或用破折号分隔的名称和进程 ID,可以选择性地包含在折叠堆栈跟踪的开头,后跟一个分号。这会将应用程序的代码路径分组到生成的火焰图中。

例如,包含以下三个堆栈跟踪的配置文件:


func_c
func_b
func_a
start_thread

func_d
func_a
start_thread

func_d
func_a
start_thread

在折叠格式中变为以下内容:


start_thread;func_a;func_b;func_c 1
start_thread;func_a;func_d 2

如果包含应用程序名称——例如,“java”——那么它将变为:


java;start_thread;func_a;func_b;func_c 1
java;start_thread;func_a;func_d 2

这种中间格式使得其他人可以为其他性能分析器贡献转换器。现在有用于 DTrace、Linux perf_events、FreeBSD pmcstat、Xperf、SystemTap、Xcode Instruments、Intel VTune、Lightweight Java Profiler、Java jstack 和 gdb 的 stackcollapse 程序4

最终的 flamegraph.pl 程序支持许多自定义选项,包括更改火焰图的标题。

作为一个示例,以下步骤获取 FlameGraph 软件,在 Linux 上收集配置文件(99 Hz,所有 CPU,60 秒),然后从配置文件生成火焰图:


# git clone https://github.com/brendangregg/FlameGraph
# cd FlameGraph
# perf record -F 99 -a -g -- sleep 60
# perf script | ./stackcollapse-perf.pl | ./flamegraph.pl > out.svg

由于 stackcollapse 的输出每条记录都只有一行,因此如果需要在生成火焰图之前进行修改,可以使用 grep/sed/awk。

在线火焰图文档包括使用其他性能分析器的说明4,5

火焰图解读

火焰图可以按如下方式解读:

• 火焰图的顶边显示在收集堆栈跟踪时正在 CPU 上运行的函数。对于 CPU 配置文件,这是直接消耗 CPU 周期的函数。对于其他配置文件类型,这是直接导致检测事件的函数。

• 寻找沿顶边的大的平台期,因为这些平台期表明单个堆栈跟踪在配置文件中经常出现。对于 CPU 配置文件,这意味着单个函数经常在 CPU 上运行。

• 自上而下阅读显示沿袭。一个函数由其父函数调用,父函数直接显示在其下方;父函数由其父函数调用,父函数显示在其下方,依此类推。从函数向下快速扫描可以识别出它被调用的原因。

• 自下而上阅读显示代码流和更大的画面。一个函数调用显示在其上方的任何子函数,而子函数又调用显示在它们上方的函数。自下而上阅读还可以显示代码流的全貌,然后再进行各种分支将执行分解为较小的塔。

• 函数框的宽度可以直接比较:较宽的框意味着在配置文件中出现的频率更高,并且是最重要的首先要理解的内容。

• 对于采用定时堆栈跟踪采样的 CPU 配置文件,如果一个函数框比另一个函数框更宽,这可能是因为它每次函数调用消耗更多的 CPU,或者该函数只是被调用得更频繁。函数调用计数不会通过采样显示或得知。

• 火焰图中的主要分支,被发现为位于单个函数之上的两个或多个大塔,可能很有用。它们可以指示代码的逻辑分组,其中一个函数分阶段处理工作,每个阶段都有自己的函数。这也可能是由条件语句引起的,条件语句选择要调用的函数。

解读示例

作为解读火焰图的示例,请考虑图 6 中显示的模拟火焰图。假设这是可视化 CPU 配置文件,该配置文件使用堆栈跟踪的定时样本收集(这是典型的)。

The Flame Graph

顶边显示函数 g() 在 CPU 上运行的时间最长;d() 更宽,但其暴露的顶边在 CPU 上运行的时间最短。包括 b()c() 在内的函数似乎没有直接在 CPU 上采样;相反,它们的子函数正在运行。

g() 下方的函数显示了它的沿袭:g()f() 调用,f()d() 调用,依此类推。

直观地比较函数 b()h() 的宽度表明,b() 代码路径在 CPU 上的运行时间大约是 h() 的四倍。每种情况下的实际 CPU 函数都是它们的子函数。

代码路径中的一个主要分支在 a() 调用 b()h() 的地方可见。理解代码为何这样做可能是其逻辑组织的关键线索。这可能是条件语句(如果条件成立,则调用 b(),否则调用 h())或阶段的逻辑分组(其中 a() 分为两个部分处理:b()h())的结果。

其他代码路径可视化

如图 1 所示,Linux perf_events 打印带有百分比注释的代码路径树。这是另一种类型的层次结构可视化:缩进的树状布局7。根据配置文件,这有时可以充分概括输出,但并非总是如此。与火焰图不同,人们无法缩小以查看整个配置文件,并且仍然可以理解这种基于文本的可视化,尤其是在百分比不再可读之后。

KCacheGrind14 使用有向无环图可视化来自配置文件数据的代码路径。这涉及将函数表示为标记框(其中宽度缩放以适应函数名称),将父子关系表示为箭头,然后将配置文件数据以百分比的形式注释在框和箭头上,带有条形图状图标。与 perf_events 的问题类似,如果将可视化缩小以适应复杂的配置文件,则注释可能不再清晰。

旭日图布局等同于火焰图使用的冰柱布局,但它使用极坐标7。虽然这可以生成有趣的形状,但存在一些困难:函数名称比矩形火焰图框中的函数名称更难绘制和阅读。此外,比较两个函数变成了比较两个角度而不是两条线段的长度,这已被评估为更困难的感知任务10

火焰图与火焰图类似的代码路径可视化(并且灵感来自火焰图13)。然而,在 x 轴上,它们显示时间的流逝,而不是字母顺序排序。这有其优点:可以识别时间顺序问题。然而,它可能会大大减少合并,当分析多个线程时,问题会加剧。当与火焰图一起使用以了解更大的画面时,它可能是理解时间顺序序列的有用选项。

挑战

火焰图的挑战主要涉及系统性能分析器,而不是火焰图本身。性能分析器通常存在两个问题:

堆栈跟踪不完整。一些系统性能分析器会截断为固定的堆栈深度(例如,10 帧),这必须增加以捕获完整的堆栈跟踪,否则帧合并可能会失败。更糟糕的问题是,当软件编译器将帧指针寄存器重用为编译器优化时,会破坏典型的堆栈跟踪收集方法。修复需要不同的编译二进制文件(例如,使用 gcc 的 -fno-omit-frame-pointer)或不同的堆栈遍历技术。

缺少函数名称。在这种情况下,堆栈跟踪是完整的,但许多函数名称都丢失了,可能表示为十六进制地址。这通常发生在 JIT(即时)编译代码中,这些代码可能不会为性能分析器创建标准符号表。根据性能分析器和运行时,有不同的修复方法。例如,Linux perf_events 支持补充符号文件,应用程序可以创建这些文件。

在 Netflix,我们在尝试为 Java 创建火焰图时遇到了这两个问题6。第一个问题已通过添加 JVM(Java 虚拟机)选项来解决——XX:+PreserveFramePointer,这允许 Linux perf_events 捕获完整的堆栈跟踪。第二个问题已使用 Java 代理 perf-map-agent11 解决,该代理为 Java 方法创建符号表。

Perl 火焰图实现的一个挑战是生成的 SVG 文件大小。对于具有数千个唯一代码路径的大型配置文件,SVG 文件的大小可能达到数十兆字节,这会导致在浏览器中加载时变得迟缓。修复方法是省略那些太细以至于在火焰图中通常不可见的代码路径。这不会影响全局视图,并使 SVG 文件保持较小。

其他配色方案

除了随机的暖色调之外,还可以使用其他火焰图配色方案,例如用于区分代码或包含额外的数据维度。

可以在 Perl 火焰图版本中选择各种调色板,包括“java”,它使用不同的色调来突出显示 Java 混合模式火焰图:绿色表示 Java 方法,黄色表示 C++,红色表示所有其他用户模式函数,橙色表示内核模式函数。图 7 显示了一个示例。(图 7 的交互式 SVG 格式版本可在 https://queue.org.cn/downloads/2016/Gregg7.svg 获取。)

The Flame Graph

另一个选项是哈希配色方案,它根据函数名称的哈希值选择颜色。这使颜色保持一致,这在比较来自同一系统的多个火焰图时很有帮助。

颜色还可以用于差异火焰图,这将在下一节中介绍。

差异火焰图

差异火焰图显示两个配置文件 A 和 B 之间的差异。Perl 火焰图软件当前支持一种方法,其中显示配置文件 B,然后使用从 A 到 B 的增量着色。红色表示增加的函数,蓝色表示减少的函数。这种方法的一个问题是,配置文件 A 中存在的一些代码路径可能完全在配置文件 B 中丢失,因此将从最终可视化中丢失。这可能会产生误导。

另一个实现 flamegraphdiff2 通过使用三个火焰图来解决这个问题。第一个显示配置文件 A,第二个显示配置文件 B,第三个仅显示它们之间的差异。鼠标悬停在任何火焰图中的一个函数上也会突出显示其他火焰图,以帮助导航。可选地,火焰图也可以使用红色/蓝色方案着色,以指示哪些代码路径增加或减少。

其他目标

如前所述,火焰图可以可视化任何性能分析器输出。这包括在 CPU PMC(性能监控计数器)溢出事件、静态跟踪事件和动态跟踪事件上收集的堆栈跟踪。以下是一些具体示例。

停顿周期

停顿周期火焰图显示通常阻塞处理器或硬件资源(通常是内存 I/O)的代码路径。输入堆栈跟踪可以使用 PMC 性能分析器收集,例如 Linux perf_events。这可以指导开发人员对已识别的代码路径采用不同的优化技术,该技术的目的是减少内存 I/O 而不是减少指令。

CPI

CPI(每指令周期数)或其倒数 IPC(每周期指令数)也是一种有助于解释 CPU 周期类型的度量,可以指导调整工作。CPI 火焰图显示 CPU 样本火焰图,其中宽度对应于 CPU 周期,但它使用从红色到蓝色的色阶来指示每个函数的 CPI:红色表示高 CPI,蓝色表示低 CPI。这可以通过捕获两个配置文件来实现——CPU 样本配置文件和指令计数配置文件——然后使用差异火焰图来着色它们之间的差异。

内存

火焰图可以通过可视化许多不同的内存事件来阐明内存增长。

通过跟踪 malloc() 函数创建的 malloc() 火焰图可视化了分配内存的代码路径。这在实践中可能很困难,因为分配器函数可能会被频繁调用,这使得在某些情况下跟踪它们的成本过高。

跟踪 brk()mmap() 系统调用可以显示导致进程虚拟内存扩展的代码路径,这通常与分配路径相关,尽管这也可能是应用程序内存的异步扩展。这些通常频率较低,使其更适合跟踪。

跟踪内存页错误显示导致进程物理内存扩展的代码路径。与分配器代码路径不同,这显示了填充已分配内存的代码。页错误通常也是较低频率的活动。

I/O

I/O 的发出,例如文件系统、存储设备和网络,通常可以使用系统跟踪器进行跟踪。这些配置文件的火焰图说明了同步发出 I/O 的不同应用程序路径。

在实践中,这揭示了其他方式无法获知的 I/O 类型。例如,磁盘 I/O 可能会发出:由应用程序同步发出,由文件系统预读例程发出,由脏数据的异步刷新发出,或由内核后台磁盘块擦除发出。I/O 火焰图通过说明导致发出磁盘 I/O 的代码路径来识别每种类型。

Off-CPU

许多性能问题在使用 CPU 火焰图时不可见,因为它们涉及线程被阻塞时花费的时间,而不是在 CPU 上运行时(Off-CPU)。线程阻塞的原因包括等待 I/O、锁、计时器、轮到 CPU 运行,以及等待分页或交换。这些场景可以通过线程被取消调度时的堆栈跟踪来识别。Off-CPU 时间也可以通过跟踪线程离开 CPU 到返回 CPU 的时间来测量。系统性能分析器通常在内核中使用静态跟踪点来跟踪这些事件。

Off-CPU 时间火焰图可以通过显示阻塞堆栈跟踪来说明此 Off-CPU 时间,其中框的宽度与阻塞时间成正比。

唤醒

在 Off-CPU 时间火焰图中实践中发现的一个问题是,当线程阻塞在条件变量上时,它们是不确定的。我们需要关于条件变量为何被其他线程持有如此之久的信息。

可以通过跟踪线程唤醒事件来生成唤醒时间火焰图。这包括其他线程释放条件变量时的唤醒,因此它们阐明了线程为何被阻塞。这种火焰图类型可以与 Off-CPU 时间火焰图一起研究,以获得有关阻塞线程的更多信息。

链式图

一个唤醒火焰图可能不够。持有条件变量的线程可能被阻塞在另一个条件变量上,该条件变量由另一个线程持有。在实践中,一个线程可能被阻塞在第二个线程上,第二个线程被阻塞在第三个线程上,而第三个线程又被阻塞在第四个线程上。

链式火焰图是一种实验性可视化3,它从 Off-CPU 火焰图开始,然后在每个阻塞堆栈的顶部添加所有唤醒堆栈跟踪。通过自下而上阅读,您可以看到阻塞的 Off-CPU 堆栈跟踪,然后是第一个唤醒它的堆栈跟踪,然后是下一个唤醒它的堆栈跟踪,依此类推。宽度对应于线程处于 Off-CPU 状态的时间以及唤醒所花费的时间。

这可以通过使用时间戳和堆栈跟踪来跟踪所有 Off-CPU 和唤醒事件,并进行后处理来实现。然而,这些事件可能非常频繁,并且使用当前工具在生产环境中进行检测是不切实际的。

未来工作

与火焰图相关的大部分工作都涉及使不同的性能分析器与不同的运行时一起工作,以便可以正确捕获火焰图的输入(例如,对于 Node.js、Ruby、Perl、Lua、Erlang、Python、Java、golang,以及使用 DTrace、perf_events、pmcstat、Xperf、Instruments 等)。未来可能会有更多此类工作。

另一个正在进行的差异火焰图,称为白色/黑色差异,使用前面描述的单个火焰图方案加上右侧的额外区域来仅显示丢失的代码路径。差异火焰图(任何类型)在未来也应该得到更广泛的应用;在 Netflix,我们正在努力为微服务每晚生成这些图:以识别回归并帮助进行性能问题分析。

其他几种火焰图实现正在开发中,探索不同的功能。Netflix 一直在开发 d3-flame-graph12,其中包括缩放时的过渡效果。希望这可以提供新的交互功能,包括一种将合并顺序从自下而上切换到自上而下的方法,以及围绕给定函数进行合并的方法。更改合并顺序已被证明对原始 flamegraph.pl 很有用,它可以选择性地自上而下合并,然后将其显示为冰柱图。自上而下的合并将叶子路径(例如,自旋锁)组合在一起。

结论

火焰图是一种用于收集的堆栈跟踪的有效可视化,适用于 CPU 性能分析以及许多其他配置文件类型。它为软件的执行创建了一个可视化地图,并允许用户导航到感兴趣的区域。与其他代码路径可视化不同,火焰图使用线段长度直观地传达信息,并且可以处理大规模配置文件,同时通常在一个屏幕上保持可读性。火焰图已成为快速理解配置文件的必备工具,并在无数次性能提升中发挥了重要作用。

致谢

通用布局、SVG 输出和 JavaScript 交互性的灵感来自 Neelakanth Nadgir 的 function_call_graph.rb 时间顺序调用堆栈可视化9,它本身受到 Roch Bourbonnais 的 CallStackAnalyzer 和 Jan Boerhout 的 vftrace 的启发。Adrien Mahieux 开发了火焰图的水平缩放功能,Thorsten Lorenz 在他的实现中添加了搜索功能8。Cor-Paul Bezemer 研究了差异火焰图并开发了第一个解决方案1。Off-CPU 时间火焰图最初由 Yichun Zhang 讨论和记录15

感谢许多其他人记录案例研究、贡献想法和代码、发表演讲、创建新的实现以及修复性能分析器以使之成为可能。请参阅更新部分以获取此项工作的列表5。最后,感谢 Deirdré Straughan 的编辑和反馈。

参考文献

1. Bezemer, C.-P. Flamegraphdiff。GitHub;http://corpaul.github.io/flamegraphdiff/

2. Bezemer, C.-P.、Pouwelse, J.、Gregg, B. 2015。使用差异火焰图理解软件性能回归。发表于 Software Analysis, Evolution and Reengineering (SANER),2015 IEEE 第 22 届国际会议;http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=7081872&newsearch=true&queryText=7081872

3. Gregg, B. 2013. 使用火焰图实现卓越性能。《第27届大型安装系统管理会议》;https://www.usenix.org/conference/lisa13/technical-sessions/plenary/gregg

4. Gregg, B. FlameGraph。GitHub;https://github.com/brendangregg/FlameGraph

5. Gregg, B. 火焰图;http://www.brendangregg.com/flamegraphs.html

6. Gregg, B., Spier, M. 2015. Java in flames。《Netflix技术博客》;http://techblog.netflix.com/2015/07/java-in-flames.html

7. Heer, J., Bostock, M., Ogievetsky, V. 2010. 可视化动物园之旅。《acmqueue》8(5);https://queue.org.cn/detail.cfm?id=1805128

8. Lorenz, T. Flamegraph。GitHub;https://github.com/thlorenz/flamegraph

9. Nadgir, N. 2007. 通过dtrace和ruby可视化调用图。《Oracle博客》;https://blogs.oracle.com/realneel/entry/visualizing_callstacks_via_dtrace_and

10. Odds, G. 2013. 数据可视化背后的科学。《Creative Bloq》;http://www.creativebloq.com/design/science-behind-data-visualisation-8135496

11. Rudolph, J. perf-map-agent。GitHub;https://github.com/jrudolph/perf-map-agent

12. Spier, M. 2015. d3-flame-graph。GitHub;https://github.com/spiermar/d3-flame-graph

13. Tikhonovsky, I. 2013. Web Inspector:为CPU性能分析器实现火焰图。《Webkit Bugzilla》;https://bugs.webkit.org/show_bug.cgi?id=111162

14. Weidendorfer, J. KCachegrind;https://kcachegrind.github.io/html/Home.html

15. Zhang, Y. 2013. 离CPU时间火焰图介绍;http://agentzh.org/misc/slides/off-cpu-flame-graphs.pdf

Brendan Gregg 是 Netflix 的高级性能架构师,在 Netflix 从事大规模计算机性能设计、分析和调优工作。他是多部技术书籍的作者,包括《系统性能》(Prentice Hall,2013)。他因在系统管理方面的杰出成就而荣获 Usenix LISA 奖。他之前曾在 Sun Microsystems 担任性能主管和内核工程师,在那里他开发了 ZFS L2ARC 并从事性能方面的工作。他还创建了许多性能分析工具,这些工具已被包含在多个操作系统中。他最近的工作包括开发性能分析的方法和可视化。

版权 © 2016 由所有者/作者持有。出版权已授权给 。

acmqueue

最初发表于《Queue》杂志第 14 卷,第 2 期——
数字图书馆中评论这篇文章








© 保留所有权利。

© . All rights reserved.