2010-06-14 73 views
3

将计数器作为参数传递给函数时,跟踪函数被调用的次数很容易。从被调用的函数返回一个也很容易。但是,我不想走这条路。这背后的原因是因为它看起来是不好的编程(让函数知道太多的信息)。有没有更好的方法来跟踪这个函数被调用了多少次?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; 
} 
+1

为什么?答案可能会改变答案。测试?监视服务器?抛开算法分析? – Stephen 2010-06-14 22:21:41

回答

15

在函数中有一个static variable,并在每次调用该函数时保持递增。

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

如果你想这样做,因为调试,然后有像gcov工具,为你做这个。 (我敢肯定,微软没有与Microsoft Visual C++捆绑在一起的替代品)

+1

什么是静态本地?您必须从被测功能内部打印出来,或者使用调试器访问它。似乎对我毫无意义...... – SoapBox 2010-06-14 23:32:14

+1

@SoapBox:是的,这就是你所做的。 – aviraldg 2010-06-14 23:42:39

+2

请注意,这不是线程安全的。 – Stephen 2010-06-16 14:08:38

2

坏的编码风格,但可能增加全局变量,如果需要互斥锁可以做的伎俩。

4

我会通过使用像gcov(这是Linux的)分析工具来做到这一点。这些程序负责在编译过程中将代码插入到程序中,并为您提供一个函数调用次数,调用时间以及程序执行该函数多长时间的报告。

3

这听起来像你正在寻找的是一个分析器。根据你使用的平台,有一些可用的工具可以帮助你寻找例程的(ab)用法。

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

+0

这让我很困扰。许多非常有知识的人似乎根据他们认为的问题所回答的问题(而不是真正问到的问题)来回答问题。有很多时候你们确实是对的,但是有时候你完全错了,最后你的回答是无用的(尽管它被许多人投票)。按照陈述回答问题,如果您还有其他要添加的内容,请在回答原始问题后添加。我道歉,今天我心情不好,请原谅我的爆发。 – Faken 2010-06-14 22:32:25

+0

完全原谅。我自己已经被原谅了,远远更大。 – fbrereto 2010-06-15 16:16:52

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; 
     /* ... */ 
    } 
}; 

将静态计数器添加到独立函数的问题是没有办法获取该值。

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

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