2010-05-06 9 views
5

Ich habe eine experimentelle Bibliothek, deren Leistung ich versuche zu messen. Um dies zu tun, ich habe folgendes geschrieben:Warum sind gettimeofday() Intervalle gelegentlich negativ?

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; 

Gelegentlich meine Ergebnisse sind negative Timings, von denen einige unsinnig. Zum Beispiel:

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

Was ist los?

+3

Sie erhalten negative, da timeval eine Mehrkomponentenstruktur ist. kurz gesagt bestehend aus Sekunden und Sekunden. wenn du naiv die üblichen komponenten im 2. tv durch den 1. tv vergleichst, bekommst du negative. Betrachten wir zum Beispiel tv1 als 1sec 3usec aus der Epoche und tv2 als 4sec und 1usec aus der Epoche.Wie Sie sehen können, erhalten Sie jetzt einen negativen Wert im Unterschied zwischen den Usec-Komponenten. –

+1

Sie haben 4 Antworten auf diese Frage erhalten, keine von ihnen kam einer korrekten Antwort nahe, aber Sie haben immer noch die irrelevantste als endgültige Antwort gewählt. –

+0

Interessante Ergänzung, aber nur relevant bei Verwendung nur einer der Komponenten, wie ich es tat (nur mit den tv_usec-Komponenten, nicht die tv_sec-Komponenten). – egpbos

Antwort

7

Sie haben einen Tippfehler. Korrigierte letzte Zeile (die Anzahl der 0er beachten):

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

BTW, timersub ist ein in Verfahren gebaut, um die Differenz zwischen zwei timevals zu bekommen.

+0

Verdammt, das ist peinlich. :) –

+3

Warum wird dies als die Antwort betrachtet? Es ist nicht korrekt, es behebt nur einen kleinen Fehler in der Darstellung der Zeit. Es geht nicht um das Kernproblem, warum negative Zeiten auftauchen. LESER HINWEIS - DIES IST KEINE GÜLTIGE ANTWORT! –

+0

@Zenikoder Ja, tut es. Gewöhnlich wäre der absolute Wert der Minuend (Sekunden * 1000000) größer als der Subtrahend, so dass selbst wenn Sie über eine Sekunde gewickelt würden, würden Sie kein Negativ erhalten. In diesem Fall war der Minuend immer zu klein (fehlende Null, Faktor 10), so dass die zweiten Wraparounds vergleichsweise große negative Zahlen im Subtrahend ergaben. –

3

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

Wie bereits erwähnt, gibt es 1000000 & mgr; s in einer Sekunde, nicht 100000.

Allgemeiner Sie können dir der Instabilität des Timings auf Computer sein müssen. Prozesse wie ntpd können die Taktzeiten ändern, was zu falschen Delta-Zeiten führt. Sie könnten an POSIX-Einrichtungen wie timer_create interessiert sein.

+0

Und die heimtückische Sache über ntpd ist, dass es in kleinen Schritten im Laufe der Zeit verteilt, so dass es schwerer zu bemerken ist. –

-1

tun

$ time ./proxy-application

nächste Mal

+0

Das lässt mich nicht Zeit das Experiment selbst. Alle von: Speicherzuordner-Initialisierung, statische Objektkonstruktion und Laden des Programms sind enthalten. Auch das ist nur in Sekunden Granularität. –

3

Die Posix-Realtime-Bibliotheken besser zur Messung hoher Genauigkeit Intervalle geeignet sind. Sie wollen wirklich nicht die aktuelle Zeit wissen. Sie wollen nur wissen, wie lange es zwischen zwei Punkten war. Dafür ist die monotone Uhr da.

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; 

Wenn Sie verknüpfen müssen Sie -lrt hinzuzufügen.

Die Verwendung der monotonen Uhr hat mehrere Vorteile. Es verwendet oft die Hardware-Timer (Hz-Kristall oder was auch immer), so ist es oft ein schnellerer Anruf als gettimeofday(). Auch monotone Timer werden garantiert nie rückwärts gehen, auch wenn ntpd oder ein Benutzer mit der Systemzeit nichts anfangen kann.

+1

Ich habe das Zeug vergessen! Mac OS implementiert die POSIX-Echtzeitbibliotheken nicht. Du hast aber vollkommen recht. –

2

Sie kümmerten sich um den negativen Wert, aber es ist immer noch nicht korrekt. Der Unterschied zwischen den Millisekunden-Variablen ist fehlerhaft, sagen wir haben Anfangs- und Endzeiten wie 1.100s und 2.051s. Bei der akzeptierten Antwort würde dies eine abgelaufene Zeit von 1.049s sein, was falsch ist.

Der folgende Code behandelt die Fälle, in denen es nur einen Unterschied von Millisekunden, aber nicht Sekunden gibt, und den Fall, dass der Millisekundenwert überläuft.

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