Профилирование для времени выполнения в C - PullRequest
0 голосов
/ 31 августа 2011

Я пытаюсь найти способ, с помощью которого я могу записать время выполнения выбранного числа функций при запуске моего инструмента.скажем, из большого списка функций, которые есть в моем инструменте, мне нужно записать, сколько времени занимают отдельные вызовы y (), z (), a1 () ....

X(){

 y();
 ..
 ..
 z();
 ..
 ..
 a1();
 ..
 ..
 b1();
 ..
 ..
}

Я не хочу использовать gprof, потому что его нужно запускать отдельно, и клиент никак не может запустить gprof в конце.Во многих случаях у меня нет доступа к тесту, который производит длительное время выполнения.Будет полезен способ регистрации времени выполнения функции высокого уровня.я не хочу оборачиваться вокруг каждого системного вызова time () и затем печатать его.Может ли макрос помочь в этом?есть идеи?

Ответы [ 3 ]

2 голосов
/ 31 августа 2011

Вы сказали, что не хотите переносить каждый вызов, но позвольте мне показать вам, как я обрабатываю вызовы по таймеру, чтобы их можно было удалить во время компиляции, и, возможно, это можно будет обернуть в другой макрос позже:

#ifndef NOTIME
#  include <ctime>
#  define CLOCK_TICK(acc, ctr)  ctr = std::clock()
#  define CLOCK_TOCK(acc, ctr)  acc += (std::clock() - ctr)
#  define CLOCK_RESET(acc) acc = 0
#  define CLOCK_REPORT(acc) 1000. * double(acc) / double(CLOCKS_PER_SEC)

static clock_t t1a, t1c, t2a, t2c; // as many pairs as you need

#else
#  define CLOCK_TICK(acc, ctr)
#  define CLOCK_TOCK(acc, ctr)
#  define CLOCK_RESET(acc)
#  define CLOCK_REPORT(acc) 0
#endif

Теперь вы можете использовать его следующим образом:

CLOCK_RESET(t1a);
for (int i = 0; i != 250000; ++i)
{
  CLOCK_TICK(t1a, t1c);
  some_expensive_function();
  CLOCK_TOCK(t1a, t1c);
}
std::cout << "Time spent in some_expensive_function(): " << CLOCK_REPORT(t1a) << "ms.\n";

С помощью переменных макросов вы можете даже завершить вызов функции:

#define timed_call(ACC, CTR, func, ...) do { CLOCK_TICK(ACC, CTR); \
                                             func(__VA_ARGS__);    \
                                             CLOCK_TOCK(ACC,CTR);  \
                                           } while (false)
1 голос
/ 31 августа 2011

Почему бы не обернуть каждый вызов макросом, подобным этому:

#define WRAP(fcall) do {\
  .. before stuff .. \
  fcall; \
  .. after call .. \
  } while(0)

затем вместо каждого

foo(x, y, z);

Вы пишете

WRAP(foo(x, y, z));

Тогда, если вы хотите отключить его, просто закомментируйте материал до / после.

Это может быть не красиво, но это работает.

1 голос
/ 31 августа 2011

Вашему клиенту не нужно запускать gprof.Если вы скомпилируете свой исполняемый файл с профилированием, ему просто нужно нормально запустить приложение, затем соберите файл данных gmon.out и доставьте его вам.Затем вы запустите gprof для генерации данных профилирования.

Если вы хотите лучше контролировать, какие части вашего кода профилируются, вы можете попробовать профилировщик Shiny с открытым исходным кодом.Для этого у вас есть ссылка на небольшую библиотеку C ++ и вставьте макрос в начало каждой функции, которую вы хотите профилировать.Есть также опции для профилирования блоков кода.Выходные данные профилировщика генерируются с помощью вызова функции из вашего приложения, поэтому вы можете решить, как и когда будут созданы выходные данные.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...