我想使用callgrind来描述我的程序,但它的速度太慢了。我想要做的是使用kcachegrind生成一个调用图,其中每个节点显示程序在哪个函数中花费了多少百分比。你能告诉我哪些功能我可以安全地禁用以获得更好的性能,所以这些信息仍然生成?
非常感谢!
Callgrind本质上是一个缓存分析器(指令和数据),它以功能级粒度工作,以重现调用图。探查器观察在程序执行期间触发事件的操作,并更新由模拟器维护的各种聚合计数器。
但是,这种高速缓存事件的细粒度模拟需要花费大量的程序运行时间。您应该知道,即使关闭了所有分析并且没有收集到有用的数据,Callgrind在运行时仍然会有至少2-4倍的命中率。积极收集数据时,平均速度会慢10-20倍。
这个理论最低值是否可以满足您的要求?如果没有,你应该考虑其他分析选项 - 讨论here。但是,如果通过一些小心的控制,加速你的程序的大型,无趣的块只有2-4倍的减速听起来合理,请继续阅读!
Callgrind提供了两种对分析数据集合的控制形式。了解它们的相互依赖关系以便做出明智的选择非常重要:
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种替代方法:
callgrind_control -i <on|off>
这需要了解您的程序执行情况以及由于部署命令的延迟而导致的准确性容忍。当然,你可以使用一些shell技巧来提供帮助。CALLGRIND_START_INSTRUMENTATION;
CALLGRIND_STOP_INSTRUMENTATION;
集合 - 同样,如果在开始时禁用,则需要围绕代码的有趣部分切换集合。 2种替代方法:
--toggle-collect=<function>
标志。根据定义,这将包括该函数中的所有子调用。如果您因此可以将特定的父函数识别为瓶颈,则这可以是隔离相关数据并将生成的调用图保持最小的有用方法。
提示:函数名称支持通配符!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个事件。
在活动检测块中,您还可以多次切换收集并转储每个块的收集统计信息。