Linux 上的 node.js 火焰图

CPU火焰图是一种有用的可视化应用程序堆栈跟踪,可让您快速识别和量化要调整的内容以提高性能。对于 Node.js,他们已经解决了使用 DTrace 对堆栈跟踪进行采样的系统上的无数问题。但是Linux呢?
在 Netflix,我们在 AWS EC2 的 Linux 实例上大规模生产 node.js,我们使用 Linux perf_events和 v8 的 --perf_basic_prof选项(也可用作 --perf-basic-prof)创建火焰图。在这篇简短的博客文章中,我将分享它的工作原理以及您如何做到这一点,以及需要修复哪些问题才能进一步改进它。
1.问题
使用 perf_events 分析 node.js 0.10.23 上的 CPU 使用情况:

img

它是交互式的:将鼠标悬停在元素上以查看详细信息,然后单击 SVG 进行缩放。 CPU 火焰图页面解释了如何解释这些,这是使用 Linux perf 部分中的说明创建的。
这个火焰图是部分有用的,因为我可以看到系统和 v8 库符号。但是,它缺少 JavaScript 符号(空白矩形),因为 v8 与 JVM 一样,可以及时编译和放置符号 (JIT)。
2. Linux perf_events JIT 支持
2009 年,Linux perf_events 添加了 JIT 符号支持,以便可以检查来自 JVM 等语言虚拟机的符号。它以以下非常简单的方式工作:
必须修改您的 JIT 应用程序以创建 /tmp/perf-PID.map 文件,这是一个包含符号地址(十六进制)、大小和符号名称的简单文本数据库。
而已。
perf 已经在查找 /tmp/perf-PID.map 文件,如果找到,它会使用它进行符号转换。所以只需要修改v8。
3. v8 --perf-basic-prof 支持
2013 年 11 月,v8 添加了 perf_events 支持,使用 --perf-basic-prof 选项启用。这使它成为节点 v0.11.13。它是这样工作的:

# ~/node-v0.11.13-linux-x64/bin/node --perf-basic-prof hello.js &
[1] 31441
# ls -l /tmp/perf-31441.map
-rw-r--r-- 1 root root 81920 Sep 17 20:41 /tmp/perf-31441.map
# tail /tmp/perf-31441.map
14cec4db98a0 f Stub:BinaryOpICWithAllocationSiteStub(ADD_CreateAllocationMementos:String*Generic->String)
14cec4db9920 f Stub:BinaryOpICWithAllocationSiteStub(ADD_CreateAllocationMementos:String*String->String)
14cec4db99a0 f Stub:BinaryOpICWithAllocationSiteStub(ADD_CreateAllocationMementos:String*Smi->String)
14cec4db9a20 22c LazyCompile:~nextTick node.js:389
14cec4db9cc0 156 Stub:KeyedLoadElementStub
14cec4db9e80 22 KeyedLoadIC:
14cec4db9f20 22 KeyedLoadIC:
14cec4db9fc0 56 Stub:DoubleToIStub
14cec4dba080 10c Stub:KeyedStoreElementStub

此文本文件是 perf_events 读取的内容。

  1. node.js 火焰图

现在我们已经使用 --perf-basic-prof 运行了节点 0.11.13+,我们可以使用以下命令创建火焰图:

$ sudo bash 
# perf record -F 99 -p `pgrep -n node` -g -- sleep 30 
# perf script > out.nodestacks01 
# git clone --depth 1 http://github.com/brendangregg/FlameGraph 
# cd FlameGraph 
# ./stackcollapse-perf.pl < ../out.nodestacks01 | ./flamegraph.pl > ../out.nodestacks01.svg

您还可以使用Dave Pacheco 的stackvis,这是一个具有额外功能的 node.js 实现。
这是一个示例结果:
请注意,JavaScript 符号现在是可读的。单击SVG放大。这个实际的火焰图不是很有趣,因为我只是在测试一个虚拟应用程序来测试 --perf-basic-prof。
感谢Trevor Norris首先在简短的要点中发布了执行此操作的说明,您可能会觉得阅读这些说明很有用。他还提供了一个脚本来促进这一点。
警告:地图文件增长
由于错误 3453,我们目前只能在短期(几小时)内使用 --perf-basic-prof :perf.map 文件可以无限增长,在几天内吃掉 Gbytes。看起来符号正在移动位置(它们应该与 --perf-basic-prof 保持一致),导致地图文件不断增长。
更新(2016 年):引入了一个新选项 --perf_basic_prof_only_functions(或 --perf-basic-prof-only-functions),通过仅记录有趣类型的符号来解决此错误,从而减少地图文件的增长。如果地图文件增长对您来说是个问题,请尝试使用此选项。
更多的
我们在 Netflix 做更多的 node.js 分析。请继续关注,并查看Netflix 技术博客。

转载翻译自: https://www.brendangregg.com