Мне нужен таймер с высоким разрешением для встроенного профилировщика в сборке Linux нашего приложения. Наши показатели профилировщика ограничены как индивидуальные функции, поэтому для этого требуется точность таймера более 25 наносекунд.
Ранее наша реализация использовала встроенную сборку и операцию rdtsc для непосредственного запроса высокочастотного таймера от ЦП, но это проблематично и требует частой повторной калибровки.
Поэтому я попытался использовать функцию clock_gettime
вместо запроса CLOCK_PROCESS_CPUTIME_ID. Документы утверждают, что это дает мне наносекундное время, но я обнаружил, что накладные расходы на один вызов clock_gettime()
превысили 250 нс. Это делает невозможным длительность событий продолжительностью 100 нс и наличие таких высоких накладных расходов на функции таймера серьезно увеличивает производительность приложения, искажая профили вне значения. (У нас есть сотни тысяч профилирующих узлов в секунду.)
Есть ли способ вызвать clock_gettime()
, который имеет меньше, чем & frac14; & mu; s накладные расходы? Или есть ли другой способ, с помощью которого я могу надежно получить счетчик временной отметки с накладными расходами < 25ns? Или я застрял с помощью rdtsc
?
Ниже приведен код, который я использовал для времени clock_gettime()
.
// calls gettimeofday() to return wall-clock time in seconds:
extern double Get_FloatTime();
enum { TESTRUNS = 1024*1024*4 };
// time the high-frequency timer against the wall clock
{
double fa = Get_FloatTime();
timespec spec;
clock_getres( CLOCK_PROCESS_CPUTIME_ID, &spec );
printf("CLOCK_PROCESS_CPUTIME_ID resolution: %ld sec %ld nano\n",
spec.tv_sec, spec.tv_nsec );
for ( int i = 0 ; i < TESTRUNS ; ++ i )
{
clock_gettime( CLOCK_PROCESS_CPUTIME_ID, &spec );
}
double fb = Get_FloatTime();
printf( "clock_gettime %d iterations : %.6f msec %.3f microsec / call\n",
TESTRUNS, ( fb - fa ) * 1000.0, (( fb - fa ) * 1000000.0) / TESTRUNS );
}
// and so on for CLOCK_MONOTONIC, CLOCK_REALTIME, CLOCK_THREAD_CPUTIME_ID.
Результаты:
CLOCK_PROCESS_CPUTIME_ID resolution: 0 sec 1 nano
clock_gettime 8388608 iterations : 3115.784947 msec 0.371 microsec / call
CLOCK_MONOTONIC resolution: 0 sec 1 nano
clock_gettime 8388608 iterations : 2505.122119 msec 0.299 microsec / call
CLOCK_REALTIME resolution: 0 sec 1 nano
clock_gettime 8388608 iterations : 2456.186031 msec 0.293 microsec / call
CLOCK_THREAD_CPUTIME_ID resolution: 0 sec 1 nano
clock_gettime 8388608 iterations : 2956.633930 msec 0.352 microsec / call
Это стандартное ядро Ubuntu. Приложение представляет собой порт приложения Windows (где наша встроенная сборка rdtsc работает отлично).
Добавление:
Имеет ли x86-64 GCC некоторый собственный эквивалент __ rdtsc(), поэтому я могу, по крайней мере, избежать встроенной сборки?