callgraph生成和分析的最小callgrind命令

时间:2018-02-01 23:02:57

标签: valgrind callgrind

我想使用callgrind来配置我的程序,但它的速度太慢了。我想要做的是使用kcachegrind生成一个调用图,其中每个节点显示程序在哪个函数中花费了多少百分比。你能告诉我哪些功能我可以安全地禁用以获得更好的性能,所以仍然会生成此信息吗?

非常感谢!

1 个答案:

答案 0 :(得分:1)

快速概览

Callgrind本质上是一个缓存分析器(指令和数据),它以功能级粒度工作,以重现调用图。探查器会在程序执行期间观察触发事件的操作,并更新模拟器维护的各种聚合计数器

但是,这种高速缓存事件的细粒度模拟会带来很大的程序运行时成本。您应该知道即使关闭所有分析并且没有收集有用的数据,Callgrind仍然会在运行时中最少约2-4x命中。积极收集数据时,平均值会慢10-20倍

这个理论最低值是否可以满足您的要求?如果没有,您应该考虑其他分析选项 - 讨论here。但是,如果通过一些小心的控制,加速你的程序的大型,无趣的块只有2-4倍的减速听起来合理,请继续阅读!

可用挂钩

Callgrind提供了两种对分析数据集合的控制形式。理解他们的相互依赖关系以便做出明智的选择非常重要:

  1. 工具状态 - 禁用时,不会观察到任何程序操作,因此不会触发任何事件或收集。模拟器基本上切换到“空闲”状态。州;这可以帮助您达到我上面提到的理论上2-4倍的最小值(参见Nulgrind)。

    但请注意,应谨慎使用!虽然它提供了有吸引力的好处,但这可能会对准确性产生重要影响。来自documentation

      

    但是,这应该谨慎使用并且粗略地使用:每个模式更改都会重置模拟器状态(即是否缓存内存块)并刷新Valgrinds内部缓存的已检测代码块,从而导致延迟切换时的罚款。

  2. 收集状态 - 禁用时,聚合计数器不会使用触发事件进行更新。这提供了一种将收集的数据简化为调用堆栈的有趣部分的方法。

    然而,直观地说,这并没有提供任何明显的执行时间加速。当然,需要启用仪器才能启用收集。

  3. 命令

    valgrind --tool=callgrind   
        --instr-atstart=<yes|no>     ;; default = yes 
        --collect-atstart=<yes|no>   ;; default = yes
        --toggle-collect=<function>  ;; Toggle collection at entry/exit of specific function
    <PROGRAM> <PROGRAM_OPTIONS>
    

    仪表 - 在开头关闭此功能表示您必须在适当的时间重新打开它。 2种替代方法:

    1. 在程序执行期间,请在适当的时候使用shell中的以下命令。

      callgrind_control -i <on|off>
      

      由于部署命令的延迟,这需要您对程序执行的可见性以及准确性的一些容忍度。当然,你可以使用一些shell技巧来提供帮助。

    2. 将以下宏插入程序代码并重新编译二进制文件。

      CALLGRIND_START_INSTRUMENTATION;
      CALLGRIND_STOP_INSTRUMENTATION;
      
    3. 集合 - 同样,如果在开始时禁用,则需要围绕代码的有趣部分切换集合。 2种替代方法:

      1. 在启动期间使用--toggle-collect=<function>标志。根据定义,这将包括该函数中的所有子调用。如果您因此可以将特定的父函数识别为瓶颈,则这可以是隔离相关数据并将生成的调用图保持最小的有用方法。

        提示:函数名称支持通配符!

      2. 在程序代码的相关部分之前和之后使用以下宏并重新编译二进制文件。这可以在函数内为您提供更细粒度的控制。

        CALLGRIND_TOGGLE_COLLECT;
        
      3. 摘要

        要结合上述所有想法,一个好的方法是:

        #include <callgrind.h>
        
        // Uninteresting program chunk
        
        CALLGRIND_START_INSTRUMENTATION;
        
        // A few extra lines to allow cache warm-up
        
        CALLGRIND_TOGGLE_COLLECT;
        // Portion to profile
        CALLGRIND_TOGGLE_COLLECT;
        
        CALLGRIND_DUMP_STATS;
        CALLGRIND_STOP_INSTRUMENTATION;
        
        // Rest of the program
        

        重新编译,并使用以下命令启动Callgrind:

        valgrind --tool=callgrind --instr-atstart=no --collect-atstart=no <PROGRAM> <PROGRAM_OPTIONS>
        

        请注意,此方法将生成2个Callgrind输出文件 - 第一个由DUMP_STATS宏创建,第二个在程序退出时生成。 DUMP_STATS在使用后将所有计数器归零,这意味着第二个日志将报告0个事件。

        在活动检测块中,您还可以多次切换收集并转储每个块的收集统计信息。