2010-05-06 20 views
5

Tengo una biblioteca experimental cuyo rendimiento estoy tratando de medir. Para ello, he escrito lo siguiente:¿Por qué los intervalos gettimeofday() ocasionalmente son negativos?

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; 

De vez en cuando, mis resultados son los tiempos negativos, algunos de los cuales no tienen sentido. Por ejemplo:

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

¿Qué está pasando?

+3

obtienes negativos porque timeval es una estructura de componentes múltiples. en resumen, formado por segundos y segundos. si ingenuamente difieres los componentes comunes en la segunda televisión por la primera televisión, obtendrás negativos. por ejemplo, considere tv1 como 1sec 3usec de epoch y tv2 como 4sec y 1usec de epoch.como puede ver, ahora obtiene un valor negativo en la diferencia entre los componentes de usec. –

+1

Tiene 4 respuestas a esta pregunta, ninguna de ellas estuvo cerca de proporcionar una respuesta correcta, pero igual seleccionó la más irrelevante como respuesta final. –

+0

Además interesante, pero solo relevante cuando se usa solo uno de los componentes, como lo estaba haciendo (solo usando los componentes tv_usec, no los de tv_sec). – egpbos

Respuesta

7

Tienes un error tipográfico. Corregido última línea (tenga en cuenta el número de 0s):

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

Por cierto, timersub está construido en un método para obtener la diferencia entre dos timevals.

+0

Maldita sea, eso es embarazoso. :) –

+3

¿Por qué se considera esto la respuesta? no es correcto, solo corrige un pequeño error en la presentación del tiempo. No trata el problema central de por qué los tiempos negativos están apareciendo. LECTORES NOTA - ¡ESTA NO ES UNA RESPUESTA VÁLIDA! –

+0

@Zenikoder Sí lo hace. Normalmente, el valor absoluto del minuendo (segundos * 1000000) sería mayor que el del sustraendo, por lo que incluso si se envuelve en un segundo, no obtendría un valor negativo. En este caso, el minuendo siempre fue demasiado pequeño (faltaba cero, factor de 10), por lo que el segundo envolvente hizo comparativamente números negativos grandes en el sustraendo. –

3

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

Como se ha señalado, hay 1000000 USEC en un segundo, no 100000.

De manera más general, es posible que tenga que ser conscientes de la inestabilidad del tiempo en las computadoras. Procesos como ntpd pueden cambiar los tiempos del reloj, lo que lleva a tiempos delta incorrectos. Es posible que le interesen las instalaciones de POSIX, como timer_create.

+0

Y lo insidioso de ntpd es que lo hace en pequeños pasos distribuidos en el tiempo, por lo que es más difícil de notar. –

-1

hacer

$ time ./proxy-application

próxima vez bibliotecas

+0

Eso no me permite cronometrar el experimento en sí. Se incluyen todos: la inicialización del asignador de memoria, la construcción de objetos estáticos y la carga del programa. Además, eso es solo en segundos de granularidad. –

3

El posix en tiempo real son más adecuados para la medición de los intervalos de alta precisión. Realmente no quieres saber la hora actual. Solo quieres saber cuánto tiempo ha pasado entre dos puntos. Para eso es el reloj monotónico.

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; 

Al vincular es necesario agregar -lrt.

Usando el reloj monótona tiene varias ventajas. A menudo utiliza los temporizadores de hardware (cristal Hz o lo que sea), por lo que a menudo es una llamada más rápida que gettimeofday(). También se garantiza que los temporizadores monótonos nunca retrocederán incluso si ntpd o un usuario está jugando con la hora del sistema.

+1

¡Me olvidé de esas cosas! Mac OS no implementa las bibliotecas POSIX en tiempo real. Sin embargo, tienes toda la razón. –

2

Se hizo cargo del valor negativo, pero todavía no es correcto. La diferencia entre las variables de milisegundos es errónea, digamos que tenemos tiempos de inicio y fin como 1.100 y 2.051. Según la respuesta aceptada, este sería un tiempo transcurrido de 1.049, que es incorrecto.

El código siguiente se ocupa de los casos en los que sólo hay una diferencia de milisegundos, pero no segundos y el caso en que se desborde el valor milisegundos.

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