2011-01-26 20 views
22

Aquí hay una pequeña prueba que he escrito para verificar que el tiempo realmente solo se ejecuta en Linux.¿Cómo detener el tiempo de ejecución hacia atrás en 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; 
} 

prueba falla con el resultado.

tv1: 1296011067 632550 
tv2: 1296011067 632549 

ummm ....

¿Por qué sucede esto?

Aquí está mi configuración:

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

Puede tener que ver con la máquina virtual. ¿Has intentado hacer esto con una instalación real de Linux? –

+0

Asegúrese de estar comprobando la conversión de enteros en tv_sec y tv_usec cada vez que haga cálculos con ellos. –

+26

Sospecho que es porque las llamadas de tiempo se dirigen a dos núcleos diferentes en su CPU y uno de ellos está cerca de un agujero negro en miniatura.Sal de la casa. Lo más rápido que puedas ¡Seriamente! – paxdiablo

Respuesta

17

Hay un open issue at the VirtualBox Bug Tracker. Que enlaza con una entrada de blog indicando por qué you shouldn't use gettimeofday() para medir el paso del tiempo:

La forma más portátil para medir el tiempo correctamente parece ser clock_gettime (CLOCK_MONOTONIC, ...)

+1

El enlace de bugtracker también señala que 'CLOCK_MONOTONIC' presenta el mismo problema, al igual que FreeBSD que se ejecuta en VirtualBox. Parece ser un error de VirtualBox. – caf

+0

El tiempo en máquinas virtuales parece ser bastante afrutado de todos modos. Mi instalación de VMWare en el trabajo de repente decidió que iba a marcar el tiempo a la mitad de la velocidad correcta. –

+0

Esto parece ser correcto. gettimeofday es problemático para mí en máquinas nativas y virtuales. clock_gettime también parece fallar para VirtualBox. El error está en VirtualBox. – user48956

5

No es que se está ejecutando hacia atrás. Sería mejor decir que no está informando la hora correcta. Esto se debe a que las computadoras, sin la ayuda de un subsistema de temporización dedicado, simplemente no son capaces de informar el tiempo con mucha precisión en intervalos de un milisegundo.

La precisión variará según el hardware, el sistema operativo e incluso la fuente de alimentación. Aquí hay un article for starters. Un poco viejo pero comunica la idea muy bien.

+0

Esta respuesta no tiene sentido. Cualquier sistema moderno tipo Unix dará precisión a una resolución de 10 milisegundos o superior, y la resolución en nanosegundos no es infrecuente. He oído que Windows tampoco funciona mal ... –

+0

@R: Estaba pensando en los viejos temporizadores de interrupción de Windows cuando cité la resolución original. Actualicé mi respuesta para los tiempos modernos ... –

10

Los temporizadores de máquina en la mayoría de las máquinas solo tienen aproximadamente 15 precisión de uso (incluso en código nativo). El tiempo de 'retroceso' es extraño, pero de todos modos no se puede confiar en ese nivel (1 usec). (También tenga en cuenta que existe una diferencia entre la precisión y la precisión, la precisión de la mayoría de los temporizadores es peor que su precisión). El uso de una máquina virtual puede agravar esto también.

actualización: Typo

+0

Gran punto sobre precisión versus precisión. Un ejemplo: RDTSC tiene una precisión extrema (sub-nanosegundo en muchas máquinas modernas) pero con una precisión potencialmente mucho peor que cualquier función normal de cronometraje. – ephemient

30

gettimeofday() no se garantiza que sea monótona. Use clock_gettime(CLOCK_MONOTONIC) si necesita esa garantía.

+0

Esto es cierto, pero el enlace de bugtracker publicado por @ vz0 dice que el mismo problema ocurre en VirtualBox con 'CLOCK_MONOTONIC', por lo que también hay un error aquí. – caf

1

Tiempo no debería correr hacia atrás en hardware real; en una VM su millaje puede variar.

En cualquier caso, su aplicación probablemente no debe suponer que el tiempo no retrocede en una cantidad muy pequeña (supongamos, tal vez 1 segundo).

Sí, clock_gettime es bueno, pero incluso ese podría ejecutar hacia atrás en el caso de hardware defectuoso (o una máquina virtual, como en su ejemplo).

He visto un error de hardware que hace que el tiempo corra hacia atrás (aunque muy ocasionalmente), fue la causa de algunos problemas muy peculiares.

En particular, cualquier cosa que implique comparar marcas de tiempo de archivos saldrá mal cuando el tiempo retroceda.