2011-01-26 10 views
22

Ecco un piccolo test che ho scritto per verificare che il tempo effettivamente funzioni solo in Linux.Come fermare il tempo a correre indietro su Linux?

#include <time.h> 
#include <sys/time.h> 

bool timeGoesForwardTest2() 
{ 
    timeval tv1, tv2; 
    double startTime = getTimeSeconds(); // my function 

    while (getTimeSeconds() - startTime < 5) 
    { 
     gettimeofday(&tv1, NULL); 
     gettimeofday(&tv2, NULL); 

     if (tv2.tv_usec == tv1.tv_usec && 
      tv2.tv_sec == tv1.tv_sec) 
     { 
     continue; // Equal times are allowed. 
     } 

     // tv2 should be greater than tv1 
     if (!(tv2.tv_usec>tv1.tv_usec || 
       tv2.tv_sec-1 == tv1.tv_sec)) 
     { 
     printf("tv1: %d %d\n", int(tv1.tv_sec), int(tv1.tv_usec)); 
     printf("tv2: %d %d\n", int(tv2.tv_sec), int(tv2.tv_usec)); 
     return false; 
     }   
    } 
    return true; 
} 

Il test ha esito negativo con il risultato.

tv1: 1296011067 632550 
tv2: 1296011067 632549 

ummm ....

Perché accade questo?

Ecco la mia messa a punto:

Linux version 2.6.35-22-generic ([email protected]) (gcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu4)) #33-Ubuntu SMP Sun Sep 19 20:34:50 UTC 2010 (Ubuntu 2.6.35-22.33-generic 2.6.35.4) 
... running inside VirtualBox 3.2.12, in Windows 7. 
+1

Potrebbe avere a che fare con la VM. Hai provato a farlo con una vera installazione Linux? –

+0

Assicurati di controllare il rollover di interi su tv_sec e tv_usec ogni volta che esegui calcoli con loro. –

+26

Sospetto che sia perché le chiamate di tempo escono da due core diversi sulla CPU e uno di loro si trova in prossimità di un buco nero in miniatura.Esci di casa. Il più velocemente possibile. Sul serio! – paxdiablo

risposta

17

C'è un open issue at the VirtualBox Bug Tracker. Si collegano ad un post sul blog che espone le ragioni you shouldn't use gettimeofday() per misurare il passaggio del tempo:

Il modo più portatile per misurare il tempo sembra correttamente per essere clock_gettime (CLOCK_MONOTONIC, ...)

+1

Il link del bugtracker evidenzia anche che 'CLOCK_MONOTONIC' presenta lo stesso problema - come fa FreeBSD in esecuzione in VirtualBox. Sembra essere un bug di VirtualBox. – caf

+0

Il tempo sulle macchine virtuali sembra essere piuttosto fruttuoso in ogni caso. La mia installazione VMWare al lavoro ha improvvisamente deciso che sarebbe stato necessario spuntare il tempo a 1/2 della frequenza corretta. –

+0

Sembra giusto. gettimeofday è problematico per me su macchine native e virtuali. clock_gettime tuttavia sembra fallire per VirtualBox. Bug è in VirtualBox. – user48956

5

Non è che è in esecuzione all'indietro. Sarebbe meglio dire che non sta riportando l'ora esatta. Questo perché i computer, senza l'ausilio di un sottosistema di temporizzazione dedicato, semplicemente non sono in grado di riportare il tempo in modo accurato in intervalli di un millisecondo.

La precisione varia a seconda dell'hardware, del sistema operativo e persino dell'alimentazione. Ecco uno article for starters. Un po 'vecchio ma comunica bene l'idea.

+0

Questa risposta non ha senso. Qualsiasi sistema moderno simile a Unix darà precisione a una risoluzione di 10 millisecondi o migliore, e la risoluzione di nanosecondi non è rara. Ho sentito che Windows non fa un brutto lavoro ... –

+0

@R: Stavo pensando alle vecchie interruzioni di Windows quando ho citato la risoluzione originale. Aggiornato la mia risposta per i tempi moderni ... –

10

I timer della macchina sulla maggior parte delle macchine hanno solo circa 15 usec di precisione (anche nel codice nativo). Il tempo che va 'indietro' è strano, ma in realtà non puoi fare affidamento su quel livello (1 usec). (Nota anche: c'è una differenza tra precisione e accuratezza, la precisione della maggior parte dei timer è peggiore della sua precisione). L'uso di una macchina virtuale può aggravare anche questo.

Aggiornamento: Typo

+0

Ottimo punto di precisione rispetto alla precisione. Caso in questione: RDTSC ha un'estrema precisione (sub-nanosecondo su molte macchine moderne) ma un'accuratezza potenzialmente peggiore di qualsiasi normale funzione di indicazione dell'ora. – ephemient

30

gettimeofday() non è garantito per essere monotona. Usa clock_gettime(CLOCK_MONOTONIC) se hai bisogno di quella garanzia.

+0

Questo è vero, ma il link bugtracker pubblicato da @ vz0 dice che lo stesso problema si verifica in VirtualBox con 'CLOCK_MONOTONIC', quindi qui c'è anche un bug. – caf

1

Tempo non dovrebbe funzionare all'indietro su hardware reale; su una VM il tuo chilometraggio può variare.

In ogni caso, la tua applicazione probabilmente non dovrebbe presumere che il tempo non scorre all'indietro di una quantità molto piccola (pensa, forse 1 secondo).

Sì, clock_gettime è buono ma anche quello potrebbe eseguire indietro nel caso di hardware difettoso (o una VM, come nell'esempio).

Ho visto un bug dell'hardware fare scorrere indietro il tempo (anche se di tanto in tanto), era una causa di alcuni problemi molto particolari.

In particolare, tutto ciò che comporta il confronto dei timestamp dei file andrà male quando il tempo torna indietro.