2010-06-14 3 views
3

Отслеживание того, сколько раз функция вызывается, легко переносить счетчик в качестве аргумента в функцию. Также легко вернуть один из вызываемой функции. Но я не хочу идти по этому пути. Причина этого в том, что это похоже на плохое программирование (позволяя функции знать слишком много информации). Есть ли лучший способ отслеживать, сколько раз эта функция была вызвана?C++: отслеживать функцию времени называется

Я просто ищу понятия, которые я мог бы изучить. Предоставление примеров кода не обязательно, но может быть полезно.

Редактировать: Я действительно не ищу инструменты для профилирования. Позвольте мне добавить код, чтобы понять свою точку зрения. Поскольку область действия funcCounter заканчивается в основном, у меня нет способа вернуть переменную myFunction, которая будет увеличивать funcCounter. Я мог бы вернуть 1 из myFunction, а затем увеличивать 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

ответ

15

У вас есть static variable в вашей функции и продолжайте увеличивать его каждый раз, когда функция в вызываемом.

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

Если вы хотите сделать это для отладки причины, то есть инструменты, такие как gcov, которые делают это для вас. (Я уверен, что у Microsoft нет альтернативы в комплекте с Microsoft Visual C++)

+1

Какое использование является статическим локальным? Вы должны либо распечатать его изнутри тестируемой функции, либо получить доступ к ней с помощью отладчика. Кажется мне совершенно бессмысленным .... – SoapBox

+1

@SoapBox: Да, вот что вы делаете. – aviraldg

+2

Обратите внимание, что это не безопасно для потоков. – Stephen

2

Плохой стиль кодирования, но, возможно, добавление глобальных переменных и, при необходимости, блокировки мьютексов могут сделать трюк.

4

Я бы сделал это с помощью инструмента для профилирования, такого как gcov (для Linux). Эти программы выполняют работу по вставке кода в вашу программу во время компиляции и дают вам отчет о том, сколько раз вызывается функция, откуда ее вызывали, и как долго программа выполняла эту функцию.

3

Похоже, что вы ищете профилировщик. В зависимости от используемой платформы имеется множество доступных инструментов, которые могут помочь вам выискивать (ab) использование рутины.

Пожалуйста, измените свой вопрос на платформе, для которой вам нужны инструменты для профилирования.

+0

Меня это очень беспокоит. Многим очень знающим людям кажется, что они отвечают на вопрос, основанный на том, о чем они думают, вопрос (в отличие от того, что на самом деле было задано). Есть много раз, что вы, ребята, действительно правы, однако бывают случаи, когда вы совершенно неправы, и в конце концов ваш ответ бесполезен (несмотря на то, что его проголосовали десятки людей). Ответьте на вопрос, как указано, и если у вас есть что-то еще для добавления, добавьте его после ответа на исходный вопрос. Прошу прощения, сегодня у меня плохое настроение, прошу простить мою вспышку. – Faken

+0

Полностью прощено. Я сам был прощен далеко, намного больше. – fbrereto

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 
Смежные вопросы