使用循环检测进行Callgrind性能分析

时间:2017-05-28 09:09:47

标签: c++ profiling callgrind kcachegrind

我第一次尝试使用Callgrind / Kcachegrind来分析我的C ++应用程序,我注意到需要花费更多时间的两个函数是:

  1. <第1周期> (50%自我)和
  2. do_lookup_x(15%自我)
  3. 现在,根据我的理解,循环1与估计递归调用函数所花费的时间有关,但我不清楚如何解释在这里花费如此之多的时间。如果有一些循环,我想看看哪个函数被更频繁地调用,并在最后花费更多的CPU时间。如果我禁用循环检测(查看 - >循环检测),则循环1消失,但是"自我"时间总和大约为60%,我不确定这是最好的事情。 关于do_lookup_x,我完全无能为力......

    您能否澄清我应该如何解释这些结果?

    提前致谢。

2 个答案:

答案 0 :(得分:0)

KCachegrind中可能未正确检测到周期: http://valgrind.org/docs/manual/cl-manual.html#cl-manual.cycles

  

6.2.4。避免周期   非正式地说,循环是一组以递归方式相互调用的函数。 ...

     

循环本身并不坏,但往往会使代码的性能分析更难。这是因为循环内呼叫的包容性成本是没有意义的。包容性成本的定义,即函数的自身成本加上其被调用者的包容性成本,需要功能之间的拓扑顺序。对于循环,这不成立:循环中函数的被调用者包括函数本身。因此,KCachegrind可以循环检测并跳过循环内调用的任何包含成本的可视化。此外,循环中的所有函数都折叠为称为循环1的人工函数。

     

现在,当一个程序暴露出非常大的周期时(对于某些GUI代码,或者使用基于事件或回调的编程风格的一般代码),你会丢失一个不错的属性,让你通过跟随调用链来查明瓶颈主要,通过包容性成本引导。此外,KCachegrind失去了显示调用图的有趣部分的能力,因为它使用包容性成本来切断不感兴趣的区域。

     

尽管循环中的包容性成本毫无意义,但可视化的一大缺点激发了在KCachegrind中临时关闭循环检测的可能性,这可能导致错误的可视化。但是,通常会出现循环,因为独立调用链的不幸叠加会导致配置文件结果看到一个循环。用非常小的测量包容性成本忽略无趣的呼叫将打破这些周期。在这种情况下,通过不检测循环来错误处理循环仍然可以提供有意义的分析可视化。

尝试在KCachegrind的“查看”菜单中关闭“循环检测”,然后选中“#34; Self"时间栏,如" Incl"将是不正确的。

您还可以尝试使用精确和完整功能堆栈保存的其他探查器。 https://github.com/jrfonseca/gprof2dot脚本支持的许多分析器可以保存完整堆栈,而不仅仅是callgrind / cachegrind格式的被调用者调用者对。

答案 1 :(得分:0)

我同意@osgx你需要一个不同的探查器,一个可以捕获整个调用堆栈的探测器。

然后,函数的包含时间百分比是一个非常简单的数字。 它只是出现该函数的堆栈样本的一小部分,无论它在单个样本中出现多少次。

这是一种思考方式。
- 假设样品每10ms采样一次,总共100秒,或10,000个样品 - 假设函数Foo出现在30%的样本上,一次或多次 - 这意味着如果你可以改变Foo所以它几乎没有时间,例如将它传递给一个非常快的子处理器,那么没有样本会看到它,因为它永远不会在堆栈上足够长的时间用于样本打它。
- 因此,30%的样本只会消失,程序需要70秒而不是100秒。 - 这意味着Foo个人负责30%的时间(无论递归)。

实际上,我更喜欢this method,因为我更感兴趣的是找出问题所在,而不是需要29%或31%。 它需要花费任何东西,它所需要的东西不会受到测量精确度的影响。

相关问题