[英]Perf Imprecise Call-Graph Report
最近的 Intel 处理器提供了一个硬件功能(又名, Precise Event-Based Sampling (PEBS)
)来访问有关 CPU state 在某些采样 CPU 事件(例如, e
)上的精确信息。 这是英特尔 64 和 IA-32 架构的软件开发人员手册:第 3 卷的摘录:
18.15.7 处理器基于事件的采样(PEBS)
基于英特尔 NetBurst 微架构的处理器中的调试存储 (DS) 机制允许收集两种类型的信息以用于调试和调整程序:PEBS 记录和 BTS 记录。
基于同一参考文献的Chapter 17
, x86-64
架构的 DS 格式如下:
BTS Buffer
记录最后N
个执行的分支( N
取决于微架构),而PEBS Buffer
记录以下寄存器: IIUC,设置了一个计数器,每个事件 (
e
) 的发生都会增加它的值。 当计数器溢出时,将向这两个缓冲区添加一个条目。 最后,当这些缓冲区达到一定大小( BTS Absolute Maximum
和PEBS Absolute Maximum
)时,会产生中断,并将两个缓冲区的内容转储到磁盘。 这会定期发生。 似乎--call-graph dwarf
回溯数据也是在同一个处理程序中提取的,对吧?
1) 这是否意味着LBR
和PEBS
( --call-graph --lbr
) state 完美匹配?
2) --call-graph dwarf
output 怎么样,它不是PEBS
的一部分(在上述参考中似乎很明显)? (某些RIP/RSP
与回溯不匹配)
准确地说,这是一个LKML Thread ,其中Milian Wolff
表明第二个问题是NO 。 但我不完全明白原因?
第一个问题的答案也是, NO (由Andi Kleen
在线程的后面消息中表示),我完全不明白。
3)这是否意味着整个DWARF
调用图信息已完全损坏?
上面的线程没有显示这一点,在我的实验中,我没有看到任何与回溯不匹配的RIP
。 换句话说,我可以相信大多数回溯吗?
我不喜欢LBR
方法,它本身可能不精确。 它还受限于回溯的大小。 虽然, 这是一个克服尺寸问题的补丁。 但这是最近的,可能是假的。
更新:
Perf
在PEBS Buffer
中仅存储一条记录? 是否只能间接强制这种配置,例如,当PEBS
事件需要调用图信息时?您引用的手册部分谈论的是 BTS,而不是 LBR:它们不是一回事。 稍后在您引用的同一线程中, Andi Kleen 似乎表明 LBR 快照时间实际上是 PMI(运行处理程序的中断)的时刻,而不是 PEBS 时刻。 所以我认为所有三种堆栈方法都有相同的问题。
DWARF 堆栈捕获肯定与 PEBS 条目不完全对应。 PEBS 事件在运行时由硬件记录,然后仅在一段时间后 CPU 中断,此时堆栈被展开。 如果 PEBS 缓冲区被配置为只保存一个条目,那么这两个东西至少应该接近,如果幸运的话,PEBS IP 将位于处理程序运行时仍在堆栈顶部的相同 function中。 在那种情况下,堆栈基本上是正确的。 由于perf
在顶部向您显示了实际的 PEBS IP,再加上捕获的帧下方的帧,因此在这种情况下最终可以正常工作。
如果您不走运,function 将在 PEBS 捕获和处理程序运行之间发生变化。 在这种情况下,您会得到一个没有意义的 franken 堆栈:顶部 function 可能无法从第二个从顶部 function (或其他东西)调用。 它并没有完全损坏:只是除了顶部帧之外的所有内容都来自捕获 PEBS 堆栈之后的某个点,而顶部帧来自 PEBS 或类似的东西。 出于同样的原因,这也适用于--call-graph fp
。
很可能您从未见过无效的 IP,因为perf
显示了 PEBS 示例中的 IP(这是整个线程的主题)。 我想如果你查看原始样本,你可以看到 PEBS IP 和处理程序 IP,你可以看到它们通常不匹配。
总体而言,您可以相信“时间”或“周期”分析的回溯,因为它们在某种意义上是执行时间的准确采样表示:只是它们不对应于 PEBS 时刻,而是一段时间后(但为什么以后的时间比 PEBS 时间差)。 基本上,对于这种类型的分析,您根本不需要 PEBS。
如果您使用的是不同类型的事件,并且您希望对事件发生的位置进行细粒度的记账,那么这就是 PEBS 的用途。 您通常不需要堆栈跟踪:只需顶部框架就足够了。 如果您想要堆栈跟踪,请使用它们,但要知道它们来自稍后的某个时刻,或者使用--lbr (if that works)
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.