2010-05-06 6 views
5

Mam eksperymentalną bibliotekę, której wydajność próbuję zmierzyć. Aby to zrobić, pisałem, co następuje:Dlaczego interwały gettimeofday() są czasami ujemne?

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; 

Czasami moje wyniki obejmują ujemne czasy, z których niektóre są bezsensowne. Na przykład:

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

Co się dzieje?

+3

Otrzymujesz negatywy, ponieważ timeval jest strukturą wieloskładnikową. w skrócie składa się z second i useconds. Jeśli naiwnie odmienicie wspólne kompozycje w drugiej telewizji przez pierwszy telewizor, otrzymacie negatywy. na przykład rozważmy tv1 jako 1sec 3usec z epoki, a tv2 to 4sec i 1usec z epoki.jak widać teraz otrzymujesz ujemną wartość różnicy między komponentami usec. –

+1

Masz 4 odpowiedzi na to pytanie, żadna z nich nie była nawet w stanie udzielić poprawnej odpowiedzi, ale wciąż wybrałeś najbardziej nieistotną jako ostateczną odpowiedź. –

+0

Interesujące uzupełnienie, ale istotne tylko przy użyciu tylko jednego z komponentów, tak jak robiłem (tylko przy użyciu komponentów tv_usec, a nie tv_sec). – egpbos

Odpowiedz

7

Masz literówkę. Poprawione ostatni wiersz (uwaga liczbę 0s):

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

BTW, timersub jest zbudowany w sposób, aby uzyskać różnicę między dwoma timevals.

+0

Cholera, to krępujące. :) –

+3

Dlaczego jest to uważane za odpowiedź? nie jest to poprawne, po prostu naprawia mały błąd w prezentacji czasu. Nie zajmuje się podstawowym problemem, dlaczego pojawiają się negatywne czasy. UWAGA CZYTELNIKÓW - TO NIE JEST WAŻNA ODPOWIEDŹ! –

+0

@Zenikoder Tak to robi. Zwykle wartość bezwzględna minuendu (sekundy * 1000000) byłaby większa niż odretnianie, więc nawet jeśli zawijałbyś przez sekundę, nie uzyskałbyś ujemnego wyniku. W tym przypadku minuenda była zawsze zbyt mała (brakowało 0, współczynnik 10), więc drugie zawijanie wykonało stosunkowo duże liczby ujemne w odroście. –

3

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

Jak wspomniano, istnieją 1000000 usec w sekundach, a nie 100000

Mówiąc bardziej ogólnie, może trzeba zdawać sobie sprawę z nietrwałości czasu na komputerach. Procesy takie jak ntpd mogą zmieniać czasy zegara, co prowadzi do nieprawidłowych czasów delta. Możesz być zainteresowany urządzeniami POSIX, takimi jak timer_create.

+0

A podstępną rzeczą w ntpd jest to, że robi to w małych krokach rozłożonych w czasie, więc trudniej to zauważyć. –

-1

zrobić

$ time ./proxy-application

następnym razem biblioteki

+0

To nie pozwala mi na sam eksperyment. Uwzględniono wszystkie: inicjalizację alokacji pamięci, statyczną budowę obiektu i ładowanie programu. Ponadto, jest to tylko w sekundach szczegółowość. –

3

POSIX czasie rzeczywistym są lepiej przystosowane do pomiaru wysokich przedziałach dokładności. Naprawdę nie chcesz znać aktualnego czasu. Chcesz tylko wiedzieć, ile czasu upłynęło pomiędzy dwoma punktami. Do tego służy monotoniczny zegar.

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; 

Po połączeniu należy dodać -lrt.

Używanie zegara monotonicznego ma kilka zalet. Często korzysta z timerów sprzętowych (kryształ Hz lub cokolwiek innego), więc często jest szybszym połączeniem niż gettimeofday(). Również monotoniczne zegary gwarantują, że nigdy nie cofną się, nawet jeśli ntpd lub użytkownik będzie wygłupiać się z czasem systemowym.

+1

Zapomniałem o tych rzeczach! Mac OS nie implementuje bibliotek czasu rzeczywistego POSIX. Masz jednak całkowitą rację. –

2

Zajęłeś się wartością ujemną, ale nadal nie jest ona poprawna. Różnica między zmiennymi milisekundowymi jest błędna, powiedzmy, że mamy czasy rozpoczęcia i zakończenia jako 1.100s i 2.051s. Przy zaakceptowanej odpowiedzi byłby to czas, który upłynął od 1.049s, co jest nieprawidłowe.

Poniższy kod zajmuje się przypadkami, w których występuje tylko różnica milisekund, ale nie sekund, oraz przypadek, w którym przepełniona jest liczba milisekund.

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);