2010-06-14 108 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