2010-05-06 4 views
5

У меня есть экспериментальная библиотека, производительность которой я пытаюсь измерить. Чтобы сделать это, я написал следующее:Почему промежутки времени gettimeofday() иногда отрицательные?

struct timeval begin; 
gettimeofday(&begin, NULL); 
{ 
    // Experiment! 
} 
struct timeval end; 
gettimeofday(&end, NULL); 

// Print the time it took! 
std::cout << "Time: " << 100000 * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) << std::endl; 

Иногда мои результаты включают в себя отрицательные моменты времени, некоторые из которых являются бессмысленными. Например:

Time: 226762 
Time: 220222 
Time: 210883 
Time: -688976 

Что происходит?

+3

вы получаете негативы, потому что timeval является многокомпонентной структурой. вкратце составленный из вторых и useconds. если вы наивно разложите общие составы во 2-м телевизоре на 1-м телевизоре, вы получите негативы. например, считать tv1 как 1сек 3 секунды от эпохи, а tv2 составляет 4 сек и 1 секунда от эпохи.как вы можете видеть, теперь вы получаете отрицательное значение в разнице между компонентами usec. – 2011-01-07 00:06:20

+1

У вас есть 4 ответа на этот вопрос, ни один из них даже не приблизился к правильному ответу, но вы все же выбрали наиболее нерелевантным в качестве окончательного ответа. – 2011-01-07 00:07:24

+0

Интересное дополнение, но актуально только при использовании только одного из компонентов, как я делал (только с использованием компонентов tv_usec, а не с tv_sec). – egpbos

ответ

7

У вас есть опечатка. Исправленная последняя строка (обратите внимание на количество 0s):

std::cout << "Time: " << 1000000 * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) << std::endl; 

BTW, timersub встроенный в метод, чтобы получить разницу между двумя timevals.

+0

Черт, это неловко. :) –

+3

Почему это считается ответом? это не правильно, он просто фиксирует небольшую ошибку в представлении времени. Он не касается основной проблемы, почему появляются отрицательные моменты. ПРИМЕЧАНИЕ ЧИТАТЕЛЕЙ - ЭТО НЕ ДЕЙСТВИТЕЛЬНО ОТВЕТ! – 2011-01-07 00:44:46

+0

@ Zenikoder Да, да. Обычно абсолютное значение minuend (секунды * 1000000) будет больше, чем вычитание, поэтому даже если вы завершите секунду, вы не получите отрицательный результат. В этом случае minuend всегда был слишком мал (отсутствовал нуль, коэффициент 10), поэтому во второй части были сделаны сравнительно большие отрицательные числа в вычитании. –

3

станд :: соиЬ < < "Время:" < < 100000 * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) < < станд :: епсИ;

Как уже отмечалось, есть 1000000 мксек в секунду, а не 100000.

В более общем плане, возможно, должны быть осведомлены о неустойчивости времени на компьютерах. Процессы, такие как ntpd, могут изменять время синхронизации, что приводит к неправильному времени дельта. Вам могут быть интересны объекты POSIX, такие как timer_create.

+0

И коварная вещь о ntpd заключается в том, что она делает это небольшими шагами, разложенными со временем, так что это труднее заметить. –

-1

делают

$ time ./proxy-application

следующий раз библиотеки

+0

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

3

в реальном времени POSIX лучше подходят для измерения высоких интервалов точности. Вы действительно не хотите знать текущее время. Вы просто хотите знать, сколько времени прошло между двумя точками. Для этого нужны монотонные часы.

struct timespec begin; 
clock_gettime(CLOCK_MONOTONIC, &begin); 
{ 
    // Experiment! 
} 
struct timespec end; 
clock_gettime(CLOCK_MONOTONIC, &end); 

// Print the time it took! 
std::cout << "Time: " << double(end.tv_sec - begin.tv_sec) + (end.tv_nsec - begin.tv_nsec)/1000000000.0 << std::endl; 

При связывании вам нужно добавить -lrt.

Использование монотонных часов имеет ряд преимуществ. Он часто использует аппаратные таймеры (хрустальный кристалл или что-то еще), поэтому часто это быстрый вызов, чем gettimeofday(). Кроме того, монотонные таймеры гарантированно никогда не возвращаются назад, даже если ntpd или пользователь работает с системным временем.

+1

Я забыл об этом! Mac OS не реализует библиотеки реального времени POSIX. Но ты совершенно прав. –

2

Вы позаботились об отрицательном значении, но все еще не правильно. Разница между миллисекундными переменными является ошибочной, скажем, что мы начинаем и заканчиваем времена как 1.100s и 2.051s. В соответствии с принятым ответом это будет истекшее время 1,049, что неверно.

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

if(end.tv_sec==begin.tv_sec) 
printf("Total Time =%ldus\n",(end.tv_usec-begin.tv_usec)); 
else 
printf("Total Time =%ldus\n",(end.tv_sec-begin.tv_sec-1)*1000000+(1000000-begin.tv_usec)+end.tv_usec);