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

问题描述 投票:0回答:1

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

非常感谢!

valgrind callgrind
1个回答
1
投票

快速概述

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

但是,这种高速缓存事件的细粒度模拟需要花费大量的程序运行时间。您应该知道,即使关闭了所有分析并且没有收集到有用的数据,Callgrind在运行时仍然会有至少2-4倍的命中率。积极收集数据时,平均速度会慢10-20倍。

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

可用挂钩

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

  1. 入侵状态 - 禁用时,不会观察到任何程序操作,因此不会触发或收集任何事件。模拟器基本上切换到“空闲”状态;这可以帮助你达到我上面提到的理论上2-4倍的最小值(参见Nulgrind)。 但要注意,这应该谨慎使用!虽然它提供了有吸引力的好处,但这可能会对准确性产生重要影响。来自documentation: 但是,这应该谨慎使用并且粗略地使用:每个模式更改都会重置模拟器状态(即,是否缓存内存块)并刷新已检测代码块的Valgrinds内部缓存,从而导致切换时的延迟损失时间。
  2. 集合状态 - 禁用时,聚合计数器不会使用触发事件进行更新。这提供了一种将收集的数据简化为调用堆栈的有趣部分的方法。 但是,直观地说,这并没有在执行时间方面提供任何明显的加速。当然,需要打开仪器才能启用收集。

命令

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;

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

  1. 在发布期间使用--toggle-collect=<function>标志。根据定义,这将包括该函数中的所有子调用。如果您因此可以将特定的父函数识别为瓶颈,则这可以是隔离相关数据并将生成的调用图保持最小的有用方法。 提示:函数名称支持通配符!
  2. 在程序代码的相关部分之前和之后使用以下宏并重新编译二进制文件。这可以在函数内为您提供更细粒度的控制。 CALLGRIND_TOGGLE_COLLECT;

摘要

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

#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个事件。

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

© www.soinside.com 2019 - 2024. All rights reserved.