C ++ obtiene tiempo de milisegundos en Linux – clock () no parece funcionar correctamente

En Windows, clock() devuelve el tiempo en milisegundos, pero en este cuadro de Linux en el que estoy trabajando, lo redondea al millar más cercano, por lo que la precisión es solo al nivel “segundo” y no al nivel de milisegundos.

Encontré una solución con Qt usando la clase QTime , instanciando un objeto y llamando a start() y luego llamando a elapsed() para obtener el número de milisegundos transcurridos.

Tengo suerte porque, para empezar, estoy trabajando con Qt, pero me gustaría una solución que no dependa de bibliotecas de terceros,

¿No hay una forma estándar de hacer esto?

ACTUALIZAR

Por favor, no recomiende Boost ..

Si Boost y Qt pueden hacerlo, seguramente no es magia, ¡debe haber algo estándar que estén usando!

Puede usar gettimeofday al comienzo y al final de su método y luego diferenciar las dos estructuras de retorno. Obtendrás una estructura como la siguiente:

 struct timeval { time_t tv_sec; suseconds_t tv_usec; } 
 #include  #include  #include  int main() { struct timeval start, end; long mtime, seconds, useconds; gettimeofday(&start, NULL); usleep(2000); gettimeofday(&end, NULL); seconds = end.tv_sec - start.tv_sec; useconds = end.tv_usec - start.tv_usec; mtime = ((seconds) * 1000 + useconds/1000.0) + 0.5; printf("Elapsed time: %ld milliseconds\n", mtime); return 0; } 

Tenga en cuenta que el clock no mide el tiempo del reloj de pared. Eso significa que si su progtwig tarda 5 segundos, el clock no medirá 5 segundos necesariamente, pero podría hacerlo más (su progtwig podría ejecutar múltiples hilos y por lo tanto podría consumir más CPU que en tiempo real) o menos. Mide una aproximación del tiempo de CPU utilizado. Para ver la diferencia, considere este código

 #include  #include  #include  int main() { std::clock_t a = std::clock(); sleep(5); // sleep 5s std::clock_t b = std::clock(); std::cout << "difference: " << (b - a) << std::endl; return 0; } 

Sale en mi sistema

 $ difference: 0 

¡Porque todo lo que hicimos fue dormir y no usar ningún tiempo de CPU! Sin embargo, usando gettimeofday obtenemos lo que queremos (?)

 #include  #include  #include  #include  int main() { timeval a; timeval b; gettimeofday(&a, 0); sleep(5); // sleep 5s gettimeofday(&b, 0); std::cout << "difference: " << (b.tv_sec - a.tv_sec) << std::endl; return 0; } 

Salidas en mi sistema

 $ difference: 5 

Si necesita más precisión pero desea obtener tiempo de CPU , puede considerar usar la función getrusage .

También recomiendo las herramientas que ofrece Boost. Ya sea el Boost Timer mencionado, o corte algo de Boost.DateTime o hay una nueva biblioteca propuesta en el sandbox – Boost.Chrono : este último será un reemplazo para el temporizador y contará con:

  • Las utilidades de tiempo de la biblioteca estándar de C ++ 0x, que incluyen:
    • duration plantilla de clase
    • Plantilla de clase time_point
    • Relojes:
      • system_clock
      • monotonic_clock
      • high_resolution_clock
  • timer plantilla de clase, con typedefs:
    • system_timer
    • monotonic_timer
    • high_resolution_timer
  • Relojes de proceso y temporizadores:
    • process_clock , capturando tiempos reales de CPU de usuario y CPU de sistema.
    • process_timer , que captura los tiempos reales transcurridos, la CPU del usuario y la CPU del sistema.
    • run_timer , reportes convenientes de | process_timer | resultados.
  • La aritmética racional en tiempo de comstackción de C ++ 0x Standard Library.

Aquí está la fuente de la lista de características

He escrito una clase Timer basada en la respuesta de CTT . Se puede usar de la siguiente manera:

 Timer timer = Timer(); timer.start(); /* perform task */ double duration = timer.stop(); timer.printTime(duration); 

Aquí está su implementación:

 #include  #include  #include  using namespace std; class Timer { private: timeval startTime; public: void start(){ gettimeofday(&startTime, NULL); } double stop(){ timeval endTime; long seconds, useconds; double duration; gettimeofday(&endTime, NULL); seconds = endTime.tv_sec - startTime.tv_sec; useconds = endTime.tv_usec - startTime.tv_usec; duration = seconds + useconds/1000000.0; return duration; } static void printTime(double duration){ printf("%5.6f seconds\n", duration); } }; 

Si no necesita que el código sea portátil para los viejos equipos, puede usar clock_gettime (), que le dará el tiempo en nanosegundos (si su procesador admite esa resolución). Es POSIX, pero desde 2001.

clock () tiene a menudo una resolución bastante pésima. Si desea medir el tiempo en el nivel de milisegundos, una alternativa es usar clock_gettime (), como se explica en esta pregunta.

(Recuerde que necesita vincular con -lrt en Linux).

Con C ++ 11 y std::chrono::high_resolution_clock puedes hacer esto:

 #include  #include  #include  typedef std::chrono::high_resolution_clock Clock; int main() { std::chrono::milliseconds three_milliseconds{3}; auto t1 = Clock::now(); std::this_thread::sleep_for(three_milliseconds); auto t2 = Clock::now(); std::cout << "Delta t2-t1: " << std::chrono::duration_cast(t2 - t1).count() << " milliseconds" << std::endl; } 

Salida:

 Delta t2-t1: 3 milliseconds 

Enlace a la demo: http://cpp.sh/2zdtu

clock () no devuelve milisegundos o segundos en Linux. Por lo general, clock () devuelve microsegundos en un sistema Linux. La forma correcta de interpretar el valor devuelto por clock () es dividirlo por CLOCKS_PER_SEC para calcular cuánto tiempo ha pasado.

Esto debería funcionar … probado en un mac …

 #include  #include  int main() { struct timeval tv; struct timezone tz; struct tm *tm; gettimeofday(&tv,&tz); tm=localtime(&tv.tv_sec); printf("StartTime: %d:%02d:%02d %d \n", tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec); } 

Sí … ejecutarlo dos veces y restar …

En el clock estándar POSIX tiene su valor de retorno definido en términos del símbolo CLOCKS_PER_SEC y una implementación es libre de definir esto de cualquier manera conveniente. Bajo Linux, he tenido buena suerte con la función times() .

gettimeofday – el problema es que puede tener valores más bajos si cambia su reloj de hardware (con NTP por ejemplo) Boost – no disponible para este reloj de proyecto () – generalmente devuelve un entero de 4 bytes, lo que significa que es una capacidad baja, y después de algún tiempo, devuelve números negativos.

Prefiero crear mi propia clase y actualizar cada 10 milisegundos, de esta manera es más flexible, e incluso puedo mejorar para tener suscriptores.

 class MyAlarm { static int64_t tiempo; static bool running; public: static int64_t getTime() {return tiempo;}; static void callback( int sig){ if(running){ tiempo+=10L; } } static void run(){ running = true;} }; int64_t MyAlarm::tiempo = 0L; bool MyAlarm::running = false; 

para actualizarlo, uso setitimer:

 int main(){ struct sigaction sa; struct itimerval timer; MyAlarm::run(); memset (&sa, 0, sizeof (sa)); sa.sa_handler = &MyAlarm::callback; sigaction (SIGALRM, &sa, NULL); timer.it_value.tv_sec = 0; timer.it_value.tv_usec = 10000; timer.it_interval.tv_sec = 0; timer.it_interval.tv_usec = 10000; setitimer (ITIMER_REAL, &timer, NULL); ..... 

Mire setitimer y ITIMER_VIRTUAL e ITIMER_REAL.

No use las funciones de alarma o uallarm, tendrá poca precisión cuando su proceso sea un trabajo duro.

Prefiero la biblioteca Boost Timer por su simplicidad, pero si no quiere usar bibliotecas de terceros, el uso de clock () parece razonable.

Como una actualización, aparece que en windows clock () mide el tiempo del reloj de pared (con la precisión CLOCKS_PER_SEC)

  http://msdn.microsoft.com/en-us/library/4e2ess30(VS.71).aspx 

mientras que en Linux mide el tiempo de CPU en los núcleos utilizados por el proceso actual

 http://www.manpagez.com/man/3/clock 

y (parece, y como lo señala el cartel original) en realidad con menos precisión que CLOCKS_PER_SEC, aunque tal vez esto dependa de la versión específica de Linux.

Me gusta el método Hola Soy de no usar gettimeofday (). Me sucedió en un servidor en ejecución, el administrador cambió la zona horaria. El reloj se actualizó para mostrar el mismo valor local (correcto). Esto hizo que la función time () y gettimeofday () cambiaran 2 horas y todas las marcas de tiempo en algunos servicios se atascaron.

Escribí una clase de C++ usando timeb .

 #include  class msTimer { public: msTimer(); void restart(); float elapsedMs(); private: timeb t_start; }; 

Funciones de miembros:

 msTimer::msTimer() { restart(); } void msTimer::restart() { ftime(&t_start); } float msTimer::elapsedMs() { timeb t_now; ftime(&t_now); return (float)(t_now.time - t_start.time) * 1000.0f + (float)(t_now.millitm - t_start.millitm); } 

Ejemplo de uso:

 #include  #include  using namespace std; int main(int argc, char** argv) { msTimer t; for (int i = 0; i < 5000000; i++) ; std::cout << t.elapsedMs() << endl; return 0; } 

La salida en mi computadora es '19'. La precisión de la clase msTimer es del orden de milisegundos. En el ejemplo de uso anterior, se realiza un seguimiento del tiempo total de ejecución ejecutado por for -loop. Esta vez incluyó el sistema operativo cambiando y entrando el contexto de ejecución de main() debido a la multitarea.