Michael_Tong
近期目标:按时吃药,努力做个正常人。

 Brendan D. Gregg 发明了火焰图,可以一针见血的指出程序的性能瓶颈,坏消息是除了OpenResty 社区,很少看到还有其他人使用火焰图。

常见的火焰图类型有 On-CPUOff-CPU,还有 MemoryHot/ColdDifferential 等等。

整个图形看起来就像一团跳动的火焰,这也正是其名字的由来。燃烧在火苗尖部的就是 CPU 正在执行的操作,不过需要说明的是颜色是随机的,本身并没有特殊的含义,纵向表示调用栈的深度,横向表示消耗的时间。因为调用栈在横向会按照字母排序,并且同样的调用栈会做合并,所以一个格子的宽度越大越说明其可能是瓶颈。综上所述,主要就是看那些比较宽大的火苗,特别留意那些类似平顶山的火苗。

要生成火焰图,必须要有一个顺手的 Tracer 工具,如果操作系统是 Linux 的话,那么选择通常是 perfsystemtap 中的一种。其中 perf 相对更常用,多数 Linux 都包含了它,有兴趣的读者稍后可以参考 Linux Profiling at Netflix 中的介绍,尤其是里面关于如何处理 Broken stacks 问题的描述,建议多看几遍,而 systemtap 相对更强大,不过缺点是你需要先学会它本身的编程语言,如果你和我一样觉得麻烦,那么我强烈推荐你使用春哥的 nginx-systemtap-toolkit,乍一看名字你可能会误以为这个工具包是 nginx 专用的,实际上这里面很多工具适用于任何 C/CPP 语言编写的程序:

那么什么时候使用 On-CPU 火焰图?什么时候使用 Off-CPU 火焰图呢?取决于当前的瓶颈到底是什么,如果是 CPU 则使用 On-CPU 火焰图,如果是 IO 或锁 则使用 Off-CPU 火焰图。如果无法确定,那么可以通过压测工具来确认:通过压测工具看看能否让 CPU 使用率趋于饱和,如果能那么使用 On-CPU 火焰图,如果不管怎么压,CPU 使用率始终上不来,那么多半说明程序被 IO 或锁卡住了,此时适合使用 Off-CPU 火焰图。如果还是确认不了,那么不妨 On-CPU 火焰图和 Off-CPU 火焰图都搞搞,正常情况下它们的差异会比较大,如果两张火焰图长得差不多,那么通常认为 CPU 被其它进程抢占了。

请按照官方说明来安装。需要着重说明的是,当你安装 kernel-devel 和 kernel-debuginfo 的时候,务必保证所安装的版本和当前内核版本一致,以 CentOS 为例:

shell> yum install yum-utils
shell> yum install kernel-devel
shell> debuginfo-install kernel

当生成的火焰图中有很多十六进制的乱码时,那么意味着对应程序缺失了 debuginfo,可以借助 gdb 来确认这一点,方法如下所示:

shell> gdb -p <PID>

好消息是如果缺失了某些 debuginfo,那么 gdb 会在结尾提示你用 debuginfo-install 命令来安装,坏消息是如果你直接运行多半没有效果,因为 CentOS 缺省没有激活对应的仓库,所以需要在「/etc/yum.repos.d/CentOS-Debuginfo.repo」中设置 enabled=1。

FlameGraph代码:https://github.com/cobblau/FlameGraph

 使用方法

1,perf record --call-graph dwarf -p 12345

2,perf script | FlameGraph/stackcollapse-perf.pl | FlameGraph/flamegraph.pl > process.svg

 

使用其他工具如何生成火焰图的方法在FlameGraph的Readme只有详细的介绍

 

上面图片中,最顶层的函数g()占用 CPU 时间最多。d()的宽度最大,但是它直接耗用 CPU 的部分很少。b()c()没有直接消耗 CPU。因此,如果要调查性能问题,首先应该调查g(),其次是i()

另外,从图中可知a()有两个分支b()h(),这表明a()里面可能有一个条件语句,而b()分支消耗的 CPU 大大高于h()

posted on 2018-03-02 10:31  Michael_Tong唐唐  阅读(5917)  评论(0编辑  收藏  举报