El problema es que hay varias funciones de tiempo diferentes disponibles en C y C++, y algunas de ellas varían en comportamiento entre implementaciones. También hay muchas medias respuestas dando vueltas. Compilar una lista de funciones de reloj junto con sus propiedades respondería la pregunta correctamente. Para empezar, preguntemos cuáles son las propiedades relevantes que estamos buscando. Mirando tu publicación, sugiero:
- ¿Qué hora mide el reloj? (real, usuario, sistema o, con suerte, ¿reloj de pared?)
- ¿Cuál es la precisión del reloj? (¿s, ms, µs o más rápido?)
- ¿Después de cuánto tiempo gira el reloj? ¿O hay algún mecanismo para evitar esto?
- ¿El reloj es monótono o cambiará con los cambios en la hora del sistema (a través de NTP, zona horaria, horario de verano, por parte del usuario, etc.)?
- ¿Cómo varía lo anterior entre implementaciones?
- ¿La función específica es obsoleta, no estándar, etc.?
Antes de comenzar la lista, me gustaría señalar que la hora del reloj de pared rara vez es el momento adecuado para usar, mientras que cambia con los cambios de zona horaria, los cambios de horario de verano o si el reloj de pared está sincronizado por NTP. Ninguna de estas cosas es buena si está utilizando el tiempo para programar eventos o para comparar el rendimiento. Solo es realmente bueno para lo que dice el nombre, un reloj en la pared (o escritorio).
Esto es lo que he encontrado hasta ahora para relojes en Linux y OS X:
time()
devuelve la hora del reloj de pared del sistema operativo, con precisión en segundos.clock()
parece devolver la suma del tiempo del usuario y del sistema. Está presente en C89 y posteriores. En un momento se suponía que este era el tiempo de CPU en ciclos, pero los estándares modernos como POSIX requieren que CLOCKS_PER_SEC sea 1000000, lo que brinda una precisión máxima posible de 1 µs. La precisión de mi sistema es de hecho 1 µs. Este reloj termina una vez que llega al tope (esto suele ocurrir después de ~2^32 tics, que no es mucho tiempo para un reloj de 1 MHz).man clock
dice que desde glibc 2.18 se implementa conclock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...)
en linuxclock_gettime(CLOCK_MONOTONIC, ...)
proporciona una resolución de nanosegundos, es monótona. Creo que los 'segundos' y los 'nanosegundos' se almacenan por separado, cada uno en contadores de 32 bits. Por lo tanto, cualquier ajuste se produciría después de muchas docenas de años de actividad. Parece un muy buen reloj, pero desafortunadamente aún no está disponible en OS X. POSIX 7 describeCLOCK_MONOTONIC
como una extensión opcional.getrusage()
resultó ser la mejor opción para mi situación. Informa los tiempos del usuario y del sistema por separado y no se ajusta. La precisión en mi sistema es de 1 µs, pero también lo probé en un sistema Linux (Red Hat 4.1.2-48 con GCC 4.1.2) y allí la precisión fue de solo 1 ms.gettimeofday()
devuelve la hora del reloj de pared con una precisión (nominal) de µs. En mi sistema, este reloj parece tener una precisión de µs, pero esto no está garantizado, porque "la resolución del reloj del sistema depende del hardware". POSIX.1-2008 dice eso. "Las aplicaciones deben usar elclock_gettime()
función en lugar del obsoletogettimeofday()
función", por lo que debe mantenerse alejado de él. Linux x86 y lo implementa como una llamada al sistema.mach_absolute_time()
es una opción para temporización de muy alta resolución (ns) en OS X. En mi sistema, esto sí da una resolución ns. En principio, este reloj se reinicia, sin embargo, está almacenando ns utilizando un número entero sin signo de 64 bits, por lo que el reinicio no debería ser un problema en la práctica. La portabilidad es cuestionable.- Escribí una función híbrida basada en este fragmento que usa clock_gettime cuando se compila en Linux, o un temporizador Mach cuando se compila en OS X, para obtener precisión ns tanto en Linux como en OS X.
Todo lo anterior existe tanto en Linux como en OS X, excepto donde se especifique lo contrario. "Mi sistema" en lo anterior es un Apple que ejecuta OS X 10.8.3 con GCC 4.7.2 desde MacPorts.
Finalmente, aquí hay una lista de referencias que encontré útiles además de los enlaces anteriores:
- http://blog.habets.pp.se/2010/09/gettimeofday-never-should-be-used-to-measure-time
- ¿Cómo medir el tiempo REAL de ejecución de un programa C bajo Linux?
- http://digitalsandwich.com/archives/27-benchmarking-misconceptions-microtime-vs-getrusage.html
- http://www.unix.com/hp-ux/38937-getrusage.html
Actualizar :para OS X, clock_gettime
ha sido implementado a partir del 10.12 (Sierra). Además, las plataformas basadas en POSIX y BSD (como OS X) comparten el rusage.ru_utime
campo de estructura.
C11 timespec_get
Ejemplo de uso en:https://stackoverflow.com/a/36095407/895245
La precisión máxima posible devuelta es de nanosegundos, pero la precisión real está definida por la implementación y podría ser menor.
Devuelve el tiempo de pared, no el uso de la CPU.
glibc 2.21 lo implementa bajo sysdeps/posix/timespec_get.c
y se reenvía directamente a:
clock_gettime (CLOCK_REALTIME, ts) < 0)
clock_gettime
y CLOCK_REALTIME
son POSIX http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html, y man clock_gettime
dice que esta medida puede tener discontinuidades si cambia alguna configuración de tiempo del sistema mientras se ejecuta su programa.
C++11 crono
Ya que estamos en eso, vamos a cubrirlos también:http://en.cppreference.com/w/cpp/chrono
GCC 5.3.0 (C++ stdlib está dentro de la fuente GCC):
high_resolution_clock
es un alias parasystem_clock
system_clock
reenvía al primero de los siguientes que esté disponible:clock_gettime(CLOCK_REALTIME, ...)
gettimeofday
time
steady_clock
reenvía al primero de los siguientes que esté disponible:clock_gettime(CLOCK_MONOTONIC, ...)
system_clock
Preguntado en:¿Diferencia entre std::system_clock y std::steady_clock?
CLOCK_REALTIME
contra CLOCK_MONOTONIC
:¿Diferencia entre CLOCK_REALTIME y CLOCK_MONOTONIC?