如何使用 KCachegrind 和 Callgrind 仅测量我的部分代码?

Posted

技术标签:

【中文标题】如何使用 KCachegrind 和 Callgrind 仅测量我的部分代码?【英文标题】:How to use KCachegrind and Callgrind to measure only parts of my code? 【发布时间】:2015-12-30 13:09:49 【问题描述】:

我想使用 valgrind 来分析我的代码。问题是,我有一个我不感兴趣的庞大启动序列。

我在 valgrind/callgrind.h 中找到了对我有帮助的定义:

CALLGRIND_START_INSTRUMENTATION CALLGRIND_STOP_INSTRUMENTATION CALLGRIND_DUMP_STATS

根据this article,我必须使用以下选项执行 valgrind

valgrind --tool=callgrind --instr-atstart=no ./application

当我这样做时,会创建两个文件:

callgrind.out.16060 callgrind.out.16060.1

然后我想使用 kcachegrind 来可视化我的结果。这很好用,但跳过我的启动序列的 makros 似乎什么也没做。我必须做些什么才能仅在我想要的地方衡量性能?

【问题讨论】:

所以,需要明确的是,您的问题不在于检测是否会损害性能,而只是您不希望从它们那里获取数据。那是对的吗?是什么让你认为宏什么也没做?您是否从启动序列中获取检测数据? 对,我不想记录数据。由于大多数列出的函数都显示了构造函数和“init()”或“config”等函数,因此很难找到我的代码的“运行时相关部分”。 当您以--instr-atstart=no 开头时,您会看到调用CALLGRIND_START_INSTRUMENTATION 之前的数据?我会确保你编译/运行了正确的代码,查看了正确的 callgrind.out 文件,等等。 是的,我清理并重新编译了整个项目。我的代码看起来像这样 void App::setup() m_ComplexSystem.config(); CALLGRIND_START_INSTRUMENTATION; m_ComplexSystem.run(); CALLGRIND_STOP_INSTRUMENTATION; CALLGRIND_DUMP_STATSM 我认为您正在查看错误的 callgrind.out.* 文件。你试过在他们两个上运行kcachegrind吗? 【参考方案1】:

假设您有以下开源程序:

int main()

    function1();

    function2();
    
    return 0;

假设您只想在 function2() 上执行 Callgrind

一种方法是在function2()周围插入Callgrind宏,然后重新编译程序(请与上面的比较):

#include <valgrind/callgrind.h>
int main()

    function1();

    CALLGRIND_START_INSTRUMENTATION;
    CALLGRIND_TOGGLE_COLLECT;
        function2();
    CALLGRIND_TOGGLE_COLLECT;
    CALLGRIND_STOP_INSTRUMENTATION;

    return 0;

在某些情况下,可能找不到callgrind.h,请参阅here for a similar problem。可能的解决方案是安装/编译valgrind-devel,参见this answer。

最后,您需要在callgrind 命令中添加两个新选项,例如:

valgrind --tool=callgrind \
    --collect-atstart=no --instr-atstart=no \ #new options
    <program>

这个答案是this entry的扩展。

【讨论】:

【参考方案2】:

我现在明白了,但我不是 100% 确定原因。我将尝试描述一下我的代码:

我有一个负责许多子系统的应用程序类。在我最初的尝试中,我尝试像这样测量应用程序内部的性能:

int main(int argc, char *argv[])

    Application a(argc, argv);
    return a.exec();


void Application::Application(int &argc, char **argv)

    m_pComplexSystem = new ComplexSystem();
    m_pComplexSystem->configure();

    CALLGRIND_START_INSTRUMENTATION;
    m_Configurator->start();    


Application::~Application()

    CALLGRIND_STOP_INSTRUMENTATION;
    CALLGRIND_DUMP_STATS;
    m_pComplexSystem ->stop();

    delete m_pComplexSystem;
    m_pComplexSystem = 0;

由于某种原因,定义被忽略了,我得到了整个构造函数的性能度量以及在 ComplexSystem 成员的 configure() 调用中所做的一切。

所以现在我使用这个似乎有效的代码:

int main(int argc, char *argv[])

    Application a(argc, argv);

    CALLGRIND_START_INSTRUMENTATION;
    int result = a.exec();
    CALLGRIND_STOP_INSTRUMENTATION;
    CALLGRIND_DUMP_STATS;
    return result;

虽然和我最初的尝试不完全一样,但我现在可以开始找慢函数了。

【讨论】:

那些愚蠢的定义...我有 int result = a.exec();然后停止检测,然后返回结果...我想这与只是执行应用程序相同,因为 callgrind 会自动停止并转储...

以上是关于如何使用 KCachegrind 和 Callgrind 仅测量我的部分代码?的主要内容,如果未能解决你的问题,请参考以下文章

kcachegrind:如何绘制完整的调用图?

如何回到 kcachegrind 的起点?

如何聚合热点(分析器)结果并在 kcachegrind 中查看

Kcachegrind。仅显示我的代码中的函数

在 kcachegrind 中显示调用树

在kcachegrind中显示调用树