Мне нужен таймер высокого разрешения для встроенного профилировщика в сборке Linux нашего приложения. Наш профилировщик измеряет области видимости как отдельные функции, поэтому для него требуется точность таймера, превышающая 25 наносекунд.
Ранее наша реализация использовала встроенную сборку и операцию rdtsc для запроса высокочастотного таймера напрямую от ЦП, но это проблематично и требует частой повторной калибровки.
Поэтому я попытался использовать вместо этого функцию clock_gettime
для запроса CLOCK_PROCESS_CPUTIME_ID. Документы утверждают, что это дает мне наносекундное время, но я обнаружил, что накладные расходы на один вызов clock_gettime()
превысили 250 нс. Это делает невозможным синхронизацию событий длительностью 100 нс, а такие высокие накладные расходы на функцию таймера серьезно снижают производительность приложения, искажая профили за пределами ценности. (У нас есть сотни тысяч узлов профилирования в секунду.)
Есть ли способ вызова clock_gettime()
, который имеет меньше служебных данных? Или есть какой-то другой способ, которым я могу надежно получить счетчик метки времени с издержками <25 нс? Или я застрял с использованием <code>rdtsc?
Ниже приведен код, который я использовал для времени clock_gettime()
.
// calls gettimeofday() to return wall-clock time in seconds:
extern double Get_FloatTime();
enum { TESTRUNS = 10244 };
// 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.
*1024* Результаты:
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 () , так что я могу хотя бы избежать встроенной сборки?