2010-05-06 13 views
5

Ho una libreria sperimentale di cui sto provando a misurare le prestazioni. Per fare questo, ho scritto il seguente:Perché gli intervalli gettimeofday() sono occasionalmente negativi?

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; 

Di tanto in tanto, i miei risultati includono tempi negativi, alcune delle quali sono prive di senso. Ad esempio:

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

Cosa sta succedendo?

+3

si ottengono i negativi perché il tempo è una struttura a più componenti. in breve composto da secondi e secondi. se si diffamano in modo ingenuo i componenti comuni nella seconda tv dal 1 ° TV, si otterranno dei negativi. per esempio considera tv1 come 1sec 3usec da epoca e tv2 da 4sec e 1usec da epoca.come puoi vedere ora ottieni un valore negativo nella differenza tra i componenti usec. –

+1

Hai 4 risposte a questa domanda, non una di queste è nemmeno arrivata vicino a fornire una risposta corretta, ma hai comunque selezionato la più irrilevante come risposta finale. –

+0

Interessante aggiunta, ma rilevante solo quando si utilizza solo uno dei componenti, come stavo facendo (solo usando i componenti tv_usec, non quelli tv_sec). – egpbos

risposta

7

Hai un errore di battitura. Corretta ultima riga (si noti il ​​numero di 0):

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

proposito, timersub è costruito in metodo per ottenere la differenza tra due timevals.

+0

Dannazione, è imbarazzante. :) –

+3

Perché questa è considerata la risposta? non è corretto, si limita a correggere un piccolo bug nella presentazione del tempo. Non affronta il problema principale del perché i tempi negativi si presentano. NOTA DEI LETTORI - QUESTA NON È UNA RISPOSTA VALIDA! –

+0

@Zenikoder Sì, sì. Normalmente, il valore assoluto del minuend (secondi * 1000000) sarebbe più grande del sottraendo, quindi, anche se lo si avvolge per un secondo, non si ottiene un risultato negativo. In questo caso, il minuend era sempre troppo piccolo (mancava zero, fattore di 10), quindi i secondi avvolgimenti facevano numeri negativi relativamente grandi nel sottraendo. –

3

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

Come già detto, ci sono 1000000 usec in un secondo, non 100000.

Più in generale, potrebbe essere necessario essere consapevoli della instabilità dei tempi su computer. Processi come ntpd possono modificare i tempi di clock, portando a tempi di delta errati. Potresti essere interessato a strutture POSIX come timer_create.

+0

E la cosa insidiosa di ntpd è che lo fa a piccoli passi sparsi nel tempo, quindi è più difficile notarlo. –

-1

fare

$ time ./proxy-application

prossima volta librerie

+0

Questo non mi lascia tempo per l'esperimento stesso. Sono inclusi tutti: inizializzazione dell'alloggiamento di memoria, costruzione di oggetti statici e caricamento del programma. Inoltre, questo è solo al secondo della granularità. –

3

POSIX in tempo reale sono più adatti per la misurazione degli intervalli di alta precisione. Davvero non vuoi sapere l'ora corrente. Vuoi solo sapere quanto tempo è rimasto tra due punti. Questo è ciò a cui serve l'orologio monotonico.

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; 

Quando ci si collega è necessario aggiungere -lrt.

L'utilizzo dell'orologio monotonico presenta diversi vantaggi. Spesso utilizza i timer hardware (cristallo Hz o qualsiasi altra cosa), quindi è spesso una chiamata più veloce di gettimeofday(). Inoltre, i timer monotonici sono garantiti per non andare mai indietro anche se ntpd o un utente sta perdendo tempo con il tempo di sistema.

+1

Mi sono dimenticato di quella roba! Mac OS non implementa le librerie realtime POSIX. Hai perfettamente ragione, però. –

2

Si è preso cura del valore negativo ma non è ancora corretto. La differenza tra le variabili del millisecondo è errata, diciamo che abbiamo orari di inizio e fine come 1.100 e 2.051. Con la risposta accettata questo sarebbe un tempo trascorso di 1.049 che non è corretto.

Il codice seguente si occupa dei casi in cui vi è solo una differenza di millisecondi ma non secondi e il caso in cui il valore dei millisecondi trabocca.

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