GNU/Linux >> Tutoriales Linux >  >> Linux

Mida el tiempo en Linux:¿tiempo frente a reloj frente a getrusage frente a clock_gettime frente a gettimeofday frente a timespec_get?

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 con clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...) en linux
  • clock_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 describe CLOCK_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 el clock_gettime() función en lugar del obsoleto gettimeofday() 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 para system_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?


Linux
  1. Linux:¿cómo medir el tiempo cuando llega un paquete?

  2. Linux:¿cómo medir y prevenir la desviación del reloj?

  3. 7 ejemplos de comandos Linux hwclock para configurar la fecha y la hora del reloj del hardware

  4. Ejemplos de comandos timedatectl en Linux

  5. Compilando C++ en una máquina Linux remota:advertencia de desviación del reloj detectada

Comando de tiempo de Linux

Último comando en Linux

Comprobar la zona horaria en Linux

Ejemplos de comandos de fecha de Linux

Entendiendo el comando time en Linux

Ping de Linux:Mostrar tiempo de espera