nodejs/v8 火焰图中的未知事件使用 perf_events
Unknown events in nodejs/v8 flamegraph using perf_events
我尝试按照 Brendan Gregg here.
的描述使用 Linux perf_events 进行一些 nodejs 分析
工作流程如下:
- 运行 node >0.11.13 with
--perf-basic-prof
,创建 /tmp/perf-(PID).map
文件,其中写入 JavaScript 符号映射。
- 使用
perf record -F 99 -p `pgrep -n node` -g -- sleep 30
捕获堆栈
- 使用 this 存储库中的
stackcollapse-perf.pl
脚本折叠堆栈
- 使用
flamegraph.pl
脚本生成svg火焰图
我得到以下结果(一开始看起来非常好):
问题是有很多 [unknown]
个元素,我想这应该是我的 nodejs 函数调用。我假设整个过程在第 3 点的某处失败,其中 perf 数据应该使用 node/v8 生成的映射折叠,并用 --perf-basic-prof
执行。 /tmp/perf-PID.map
文件已创建并在节点执行期间将一些映射写入其中。
如何解决这个问题?
我使用的是 CentOS 6.5 x64,并且已经在节点 0.11.13、0.11.14(预构建和编译)上尝试过,但没有成功。
首先,“[未知]”的意思是采样器无法找出函数的名称,因为它是系统或库函数。
如果是这样,那没关系 - 你不在乎,因为你正在 你的 代码中寻找负责时间的东西,而不是系统代码。
实际上,我建议这是其中之一 XY questions。
即使你得到了对你所问问题的直接回答,它也可能没有什么用处。
原因如下:
1. CPU 分析在 I/O 绑定程序中用处不大
你的火焰图中左边的两座塔正在做 I/O,所以它们可能比右边的大堆 wall-time 多得多。
如果这个火焰图来自 wall-time 个样本,而不是 CPU-time 个样本,它可能看起来更像下面的第二张图,它告诉你时间实际流向了哪里:
右边的一大堆 juicy-looking 有 sh运行k,所以它远没有那么重要。
另一方面,I/O 塔非常宽。
那些宽橙色条纹中的任何一个,如果它在您的代码中,都代表着一个节省大量时间的机会,如果可以避免某些 I/O。
2。无论程序是 CPU- 还是 I/O-bound,加速机会都可以很容易地从火焰图中隐藏
假设某个函数 Foo
确实在做一些浪费的事情,如果您知道它,就可以修复它。
假设在火焰图中,它是暗红色。
假设它是从代码中的许多地方调用的,所以它不会全部收集在火焰图中的一个位置。
相反,它出现在此处用黑色轮廓显示的多个小地方:
注意,如果收集了所有这些矩形,您可以看到它占了 11% 的时间,这意味着它值得一看。
如果你能将它的时间减半,你可以整体节省 5.5%。
如果实际上可以完全避免它正在做的事情,那么您总体上可以节省 11%。
这些小矩形中的每一个都会缩小为零,并将图形的其余部分拉到它的右边。
现在我将向您展示the method I use。我抽取了适量的随机堆栈样本,并检查每一个样本中是否存在可以加速的例程。
这对应于像这样在火焰图中采样:
细长的垂直线代表二十个 random-time 堆栈样本。
如您所见,其中三个标有 X。
这些是通过 Foo
的那些。
这是正确的数字,因为 11% 乘以 20 是 2.2。
(困惑?好吧,这是给你的一个小概率。如果你抛硬币 20 次,它有 11% 的几率出现正面,你会得到多少正面?从技术上讲,这是一个二项分布。你最有可能得到的数字是 2,下一个最有可能的数字是 1 和 3。(如果你只得到 1,你继续前进直到得到 2。)这是分布:)
(要查看 Foo
两次的平均样本数是 2/0.11 = 18.2 个样本。)
查看这 20 个样本可能看起来有点令人生畏,因为它们 运行 的深度在 20 到 50 之间。
但是,您基本上可以忽略所有不属于您的代码。
只需检查它们是否有你的代码。
你会准确地看到你是如何度过时间的,
你会非常粗略地测量出多少。
深筹码既是坏消息也是好消息——
他们的意思是代码可能有很大的加速空间,和他们告诉你那些是什么。
任何你看到的可以加速的东西,如果你在不止一个样本上看到它,都会给你一个健康的加速,保证。
您需要在多个样本上看到它的原因是,如果您只在一个样本上看到它,您只知道它的时间不为零。如果你在不止一个样品上看到它,你仍然不知道它需要多少时间,但你知道它并不小。
Here are the statistics.
一般来说,不同意主题专家的观点是个坏主意,但(怀着最大的敬意)我们开始吧!
SO 敦促答案执行以下操作:
"Please be sure to answer the question. Provide details and share your research!"
所以问题是,至少我的解释是,为什么 perf 脚本输出中有 [unknown] 帧(以及如何将这些 [unknown] 帧转换为有意义的名称)?
这个问题 可能 是关于 "how to improve the performance of my system?" 但在这个特殊情况下我不这么认为。关于如何 post 处理 perf 记录数据,这里存在一个真正的问题。
问题的答案是虽然先决条件设置是正确的:正确的节点版本,存在正确的参数以生成函数名称 (--perf-basic-prof), 生成的 perf 映射文件必须由 root 拥有,perf 脚本才能产生预期的输出。
就是这样!
今天写了一些新脚本,我想到了这个,把我带到了这个 SO 问题。
这里有一些额外的参考资料:
https://yunong.io/2015/11/23/generating-node-js-flame-graphs/
[有时可以强制非根文件]http://www.spinics.net/lists/linux-perf-users/msg02588.html
我尝试按照 Brendan Gregg here.
的描述使用 Linux perf_events 进行一些 nodejs 分析工作流程如下:
- 运行 node >0.11.13 with
--perf-basic-prof
,创建/tmp/perf-(PID).map
文件,其中写入 JavaScript 符号映射。 - 使用
perf record -F 99 -p `pgrep -n node` -g -- sleep 30
捕获堆栈
- 使用 this 存储库中的
stackcollapse-perf.pl
脚本折叠堆栈 - 使用
flamegraph.pl
脚本生成svg火焰图
我得到以下结果(一开始看起来非常好):
问题是有很多 [unknown]
个元素,我想这应该是我的 nodejs 函数调用。我假设整个过程在第 3 点的某处失败,其中 perf 数据应该使用 node/v8 生成的映射折叠,并用 --perf-basic-prof
执行。 /tmp/perf-PID.map
文件已创建并在节点执行期间将一些映射写入其中。
如何解决这个问题?
我使用的是 CentOS 6.5 x64,并且已经在节点 0.11.13、0.11.14(预构建和编译)上尝试过,但没有成功。
首先,“[未知]”的意思是采样器无法找出函数的名称,因为它是系统或库函数。 如果是这样,那没关系 - 你不在乎,因为你正在 你的 代码中寻找负责时间的东西,而不是系统代码。
实际上,我建议这是其中之一 XY questions。 即使你得到了对你所问问题的直接回答,它也可能没有什么用处。 原因如下:
1. CPU 分析在 I/O 绑定程序中用处不大
你的火焰图中左边的两座塔正在做 I/O,所以它们可能比右边的大堆 wall-time 多得多。 如果这个火焰图来自 wall-time 个样本,而不是 CPU-time 个样本,它可能看起来更像下面的第二张图,它告诉你时间实际流向了哪里:
右边的一大堆 juicy-looking 有 sh运行k,所以它远没有那么重要。 另一方面,I/O 塔非常宽。 那些宽橙色条纹中的任何一个,如果它在您的代码中,都代表着一个节省大量时间的机会,如果可以避免某些 I/O。
2。无论程序是 CPU- 还是 I/O-bound,加速机会都可以很容易地从火焰图中隐藏
假设某个函数 Foo
确实在做一些浪费的事情,如果您知道它,就可以修复它。
假设在火焰图中,它是暗红色。
假设它是从代码中的许多地方调用的,所以它不会全部收集在火焰图中的一个位置。
相反,它出现在此处用黑色轮廓显示的多个小地方:
注意,如果收集了所有这些矩形,您可以看到它占了 11% 的时间,这意味着它值得一看。 如果你能将它的时间减半,你可以整体节省 5.5%。 如果实际上可以完全避免它正在做的事情,那么您总体上可以节省 11%。 这些小矩形中的每一个都会缩小为零,并将图形的其余部分拉到它的右边。
现在我将向您展示the method I use。我抽取了适量的随机堆栈样本,并检查每一个样本中是否存在可以加速的例程。 这对应于像这样在火焰图中采样:
细长的垂直线代表二十个 random-time 堆栈样本。
如您所见,其中三个标有 X。
这些是通过 Foo
的那些。
这是正确的数字,因为 11% 乘以 20 是 2.2。
(困惑?好吧,这是给你的一个小概率。如果你抛硬币 20 次,它有 11% 的几率出现正面,你会得到多少正面?从技术上讲,这是一个二项分布。你最有可能得到的数字是 2,下一个最有可能的数字是 1 和 3。(如果你只得到 1,你继续前进直到得到 2。)这是分布:)
(要查看 Foo
两次的平均样本数是 2/0.11 = 18.2 个样本。)
查看这 20 个样本可能看起来有点令人生畏,因为它们 运行 的深度在 20 到 50 之间。 但是,您基本上可以忽略所有不属于您的代码。 只需检查它们是否有你的代码。 你会准确地看到你是如何度过时间的, 你会非常粗略地测量出多少。 深筹码既是坏消息也是好消息—— 他们的意思是代码可能有很大的加速空间,和他们告诉你那些是什么。
任何你看到的可以加速的东西,如果你在不止一个样本上看到它,都会给你一个健康的加速,保证。 您需要在多个样本上看到它的原因是,如果您只在一个样本上看到它,您只知道它的时间不为零。如果你在不止一个样品上看到它,你仍然不知道它需要多少时间,但你知道它并不小。 Here are the statistics.
一般来说,不同意主题专家的观点是个坏主意,但(怀着最大的敬意)我们开始吧!
SO 敦促答案执行以下操作:
"Please be sure to answer the question. Provide details and share your research!"
所以问题是,至少我的解释是,为什么 perf 脚本输出中有 [unknown] 帧(以及如何将这些 [unknown] 帧转换为有意义的名称)? 这个问题 可能 是关于 "how to improve the performance of my system?" 但在这个特殊情况下我不这么认为。关于如何 post 处理 perf 记录数据,这里存在一个真正的问题。
问题的答案是虽然先决条件设置是正确的:正确的节点版本,存在正确的参数以生成函数名称 (--perf-basic-prof), 生成的 perf 映射文件必须由 root 拥有,perf 脚本才能产生预期的输出。
就是这样!
今天写了一些新脚本,我想到了这个,把我带到了这个 SO 问题。
这里有一些额外的参考资料:
https://yunong.io/2015/11/23/generating-node-js-flame-graphs/
[有时可以强制非根文件]http://www.spinics.net/lists/linux-perf-users/msg02588.html