C ++:跟踪调用函数的时间

时间:2010-06-14 22:16:21

标签: c++

在将计数器作为参数传递给函数时,跟踪调用函数的次数很容易。从被调用函数返回一个时也很容易。但是,我不想走那条路。这背后的原因是因为它似乎是糟糕的编程(让函数知道太多信息)。有没有更好的方法来跟踪调用此函数的次数?

我只是在寻找可以学习的概念。提供代码示例不是必需的,但可能会有所帮助。

编辑:我实际上并不是在寻找分析工具。让我添加一些代码来解释我的观点。因为funcCounter的范围以main结尾,所以我无法从myFunction返回一个将增加funcCounter的变量。我可以从myFunction返回1,然后以这种方式递增funcCounter,但这似乎不是很好的编程。还有其他办法吗?

int main()
{
int funcCounter = 0;
char *mystring = "This is a silly function.";
myFunction(mystring);
cout << "Times function is called: " << funcCounter << endl;
    return 0;
}

void myFunction(char *mystring)
{
cout << mystring << endl;
}

6 个答案:

答案 0 :(得分:18)

在函数中有一个static variable,并且每次调用函数时都会递增它。

void my_Function(void) {
    static unsigned int call_count = 0;
    call_count++;
}

如果您想出于调试原因这样做,那么有gcov这样的工具可以帮您完成。 (我很确定Microsoft没有与Microsoft Visual C ++捆绑的替代方案)

答案 1 :(得分:4)

我会通过使用像gcov(用于linux)的分析工具来做到这一点。这些程序在编译期间执行将代码插入程序的工作,并向您报告函数被调用的次数,调用函数的位置以及程序执行该函数所花费的时间。

答案 2 :(得分:3)

听起来你正在寻找的是一个探查器。根据您使用的平台,有一系列可用的工具可以帮助您查找例程的(ab)使用。

请使用您需要分析工具的平台修改您的问题。

答案 3 :(得分:3)

如果该函数是类的一部分,则可以向该类添加static计数器,以及访问器和/或重置函数:

class X
{
private:
    /* diagnostics */
    static int counter = 0;
    int read_counter() const { return counter; }
    void reset_counter() { counter = 0; }

public:
    /* real code */
    fcn() {
        ++counter;
        /* ... */
    }
};

向独立函数添加静态计数器的问题在于无法获得该值。

当然,您可以添加全局,但不是原始全局,而是建议包含所有诊断代码和数据的单例实例。

答案 4 :(得分:3)

使用类似这样的类,只需在函数(或任何其他块)的顶部实例化它,就像在下面f()中完成的那样。

注意:gettimeofday()有一些开销,所以你可能想要使用不同的计时方法,但这是一个完全不同的主题,值得它自己的问题(并且之前已在SO上解决)。

#include <iostream>
#include <string>
#include <map>
#include <sstream>
#include <ctime>
#include <cstdlib>
#include <sys/time.h>

class PerfStats 
{
private:
    std::string which_;
    timeval begin_;

public:

    PerfStats(std::string const &file, int line)
    {
        std::stringstream ss;
        ss << file << ':' << line;
        which_ = ss.str();
        gettimeofday(&begin_, NULL);
    }

    ~PerfStats()
    {
        timeval end;

        gettimeofday(&end, NULL);

        Times[which_] = (end.tv_sec - begin_.tv_sec) + (end.tv_usec - begin_.tv_usec)/1000000.0;
        ++Counts[which_];
    }

    static std::map<std::string, double> Times;
    static std::map<std::string, unsigned int> Counts;

    static void Print()
    {
        for(std::map<std::string, double>::iterator it = Times.begin(); it != Times.end(); ++it)
            std::cout << it->first << " :\t" << it->second << "s" << std::endl;

        for(std::map<std::string, unsigned int>::iterator it = Counts.begin(); it != Counts.end(); ++it)
            std::cout << it->first << " :\t" << it->second << " times" << std::endl;
    }
};


std::map<std::string, double> PerfStats::Times;
std::map<std::string, unsigned int> PerfStats::Counts;

void f()
{
    PerfStats(__FILE__, __LINE__);
    usleep(1);
}

main()
{
    srand(time(NULL));

    for(int i = 0; i < rand(); ++i)
        f();
    PerfStats::Print();
}

示例输出:

test.cpp:54 :   2e-06s
test.cpp:54 :   21639 times

答案 5 :(得分:2)

编码风格不好,但可能会添加全局变量,如果需要,互斥锁可能会起作用。