Мне нужен таймер с высоким разрешением для встроенного профилировщика в сборку Linux нашего приложения. Наш профилировщик измеряет такие маленькие области, как отдельные функции, поэтому ему требуется точность таймера лучше 25 наносекунд.
Ранее наша реализация использовала встроенную сборку и операцию rdtsc для запроса высокочастотного таймера напрямую от ЦП, но это проблематично и требует частой повторной калибровки.
Поэтому я попытался использовать функцию clock_gettime
вместо запроса CLOCK_PROCESS_CPUTIME_ID. Документы утверждают, что это дает мне время наносекунд, но я обнаружил, что накладные расходы на один вызов clock_gettime ()
превышают 250 нс. Это делает невозможным синхронизацию событий длительностью 100 нс, а такие высокие накладные расходы на функцию таймера серьезно снижают производительность приложения, искажая профили сверх значения. (У нас есть сотни тысяч узлов профилирования в секунду.)
Есть ли способ вызвать clock_gettime ()
с накладными расходами менее µs? Или есть другой способ, которым я могу надежно получить счетчик отметок времени с накладными расходами 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 () , чтобы я мог по крайней мере избежать встроенной сборки?