Académique Documents
Professionnel Documents
Culture Documents
Leí por allí que aquellas personas que nunca se preocuparon por la velocidad con la que
corren sus programas, son perfectos candidatos para jugar con JAVA, no utilizo JAVA, así
que no puedo sustentarlo.
Bien, pero entonces, ¿qué función usar para tomar el tiempo del reloj?
Y más importante aún, ¿qué precisión obtenemos con dicha función?
Para capturar el valor del tiempo podemos utilizar la rutina clock(), que devuelve el tiempo
aproximado de CPU que transcurrió desde que nuestro programa fue iniciado, dicho tiempo
representado en un valor de tipo clock_t: un valor entero que indica una cantidad de "tics" de
reloj.
La precisión que tenemos con dicha rutina es de CLOCKS_PER_SEC (tics de reloj por
segundo), lo que significa que por cada segundo que pasa, la función clock() nos devolverá
CLOCKS_PER_SEC unidades más que el valor anterior. En MinGW, CLOCKS_PER_SEC
es igual a 1000, pero es mejor no fiarse de esto, ya que en otras plataformas dicho valor varía.
Inclusive, según POSIX, la constante CLOCKS_PER_SEC debería ser 1000000.
t_ini = clock();
/* ...hacer algo... */
t_fin = clock();
1. Tomar una medida única y aislada es igual que tomar un número completamente
aleatorio y mostrarlo (no es una muestra representativa). Es mejor repetir las
mediciones unas cuantas veces (y hablo del orden de las 100, o 100000, o 1e32 veces),
y luego sacar un promedio de todo.
2. La función clock() no llega a tener una precisión ni de 10 milisegundos (aunque
CLOCS_PER_SEC sea 1000 o más).
Una vez dicho esto, el código de arriba sirve para nada. Así que tenemos que buscar una
función con mayor precisión, y además, promediar varias muestras.
Existen otras alternativas como la función gettimeofday, pero bajo Windows sufre del mismo
problema de precisión que clock(). Igualmente en Linux funciona perfectamente, así que vale
la pena tener en cuenta este código:
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
gettimeofday(&t_ini, NULL);
/* ...hacer algo... */
gettimeofday(&t_fin, NULL);
Como puede ver la estructura timeval contiene dos campos, segundos y microsegundos
transcurridos (tv_sec y tv_usec respectivamente), por lo tanto ofrece una precisión de
microsegundos. De todas formas, como decía, esto en Windows no sirve y la razón es
sencilla, en la misma MSDN explican que el temporizador del sistema corre
aproximadamente a unos 10 milisegundos, por lo tanto, cualquier función que lo utilice nos
estará dando la misma asquerosa precisión (inclusive al utilizar GetSystemTimeAsFileTime y
FILETIME).
QueryPerformanceCounter(&t_ini);
/* ...hacer algo... */
QueryPerformanceCounter(&t_fin);
Acá transcribo una macro para medir el tiempo de una rutina en Linux mediante
clock_gettime:
#define TIME_THIS(X) \
{ \
struct timespec ts1, ts2; \
\
clock_gettime( CLOCK_REALTIME, &ts1 ); \
\
X; \
\
clock_gettime( CLOCK_REALTIME, &ts2 ); \
\
printf( #X " demora: %f\n", \
(float) ( 1.0*(1.0*ts2.tv_nsec - ts1.tv_nsec*1.0)*1e-9 \
+ 1.0*ts2.tv_sec - 1.0*ts1.tv_sec ) ); \
}