C ++ obtener milisegundos de tiempo en Linux - reloj () no parece funcionar correctamente

StackOverflow https://stackoverflow.com/questions/588307

  •  09-09-2019
  •  | 
  •  

Pregunta

En Windows, clock() devuelve el tiempo en milisegundos, pero en esta máquina Linux que estoy trabajando, se redondea al 1000 más cercana por lo que la precisión es sólo para el "segundo" nivel y no al nivel de milisegundos.

he encontrado una solución con Qt utilizando la clase QTime, instanciar un objeto y llamar start() en ella, luego llamando elapsed() para obtener el número de milisegundos transcurridos.

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

¿No hay manera estándar de hacer esto?

Actualizar

Por favor, no lo recomiendan Boost ..

Si Boost y Qt pueden hacerlo, sin duda no es magia, tiene que haber algo estándar que están usando!

¿Fue útil?

Solución

Se puede usar gettimeofday al comienzo y al final de su método y luego diferencia de las dos estructuras de retorno. Usted obtendrá una estructura como la siguiente:

struct timeval {
  time_t tv_sec;
  suseconds_t tv_usec;
}

Otros consejos

#include <sys/time.h>
#include <stdio.h>
#include <unistd.h>
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 clock hace no pared de medida hora del reloj. Eso significa que si el programa dura 5 segundos, clock no medirá 5 segundos necesariamente, pero podría más (el programa puede ejecutar múltiples hilos y así podría consumir más recursos de CPU que en tiempo real) o menos. Mide una aproximación de tiempo de CPU utiliza. Para ver la diferencia en cuenta este código

#include <iostream>
#include <ctime>
#include <unistd.h>

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;
}

Se emite en mi sistema

$ difference: 0

Debido a que todo lo que hicimos estaba durmiendo y no usar ningún tiempo de CPU! Sin embargo, el uso de gettimeofday conseguimos lo que queremos (?)

#include <iostream>
#include <ctime>
#include <unistd.h>
#include <sys/time.h>

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;
}

Las salidas en mi sistema

$ difference: 5

Si necesita más precisión, pero desea conseguir tiempo de CPU , entonces se puede considerar el uso de la función getrusage.

También recomiendo las herramientas ofrecidas por Boost. O bien el temporizador Boost mencionado, o piratear algo fuera de Boost.DateTime o hay nueva biblioteca se propone en la caja de arena - Boost.Chrono : Este último será un reemplazo para el temporizador y contará con:

  • Utensilios de tiempo El C ++ 0x de la biblioteca estándar, incluyendo:
    • plantilla de clase duration
    • 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
  • Proceso de relojes y temporizadores:
    • process_clock, la captura de bienes, de uso de la CPU y el sistema de la CPU veces.
    • process_timer, capturando transcurrido real, el usuario de la CPU, y el sistema de la CPU veces.
    • run_timer, la presentación de informes conveniente de | process_timer | resultados.
  • en tiempo de compilación aritmética racional El 0x de biblioteca estándar de C ++.

Aquí es el fuente de la lista de características

He escrito una clase Timer basado en CTT de respuesta . Puede ser utilizado de la siguiente manera:

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

Aquí es su aplicación:

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
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 usted no necesita el código para ser portátil a los viejos sistemas Unix, puede utilizar clock_gettime (), el cual le dará el tiempo en nanosegundos (si su procesador es compatible con esa resolución). Es POSIX, pero a partir de 2001.

reloj () tiene una resolución menudo bastante pésimo. Si desea medir el tiempo en el nivel de milisegundo, una alternativa es utilizar clock_gettime (), como explica en esta pregunta.

(Recuerde que es necesario enlazar con -lrt en Linux).

Con C ++ 11 y std::chrono::high_resolution_clock usted puede hacer esto:

#include <iostream>
#include <chrono>
#include <thread>
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<std::chrono::milliseconds>(t2 - t1).count()
              << " milliseconds" << std::endl;
}

Salida:

Delta t2-t1: 3 milliseconds

Enlace a la demostración: http://cpp.sh/2zdtu

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

Esto debería funcionar ... probado en un mac ...

#include <stdio.h>
#include <sys/time.h>

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 se define en términos del símbolo CLOCKS_PER_SEC y una implementación es libre de definir esto en cualquier forma conveniente. Bajo Linux, he tenido buena suerte con la función times().

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

Yo prefiero crear mi propia clase y actualizar cada 10 milisegundos, por lo que de esta manera es más flexible, e incluso puedo mejorarlo 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 refrescar que utilizo 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); 
.....

Mira setitimer y la ITIMER_VIRTUAL y ITIMER_REAL.

No utilice las funciones de alarma o UAlarm, tendrá poca precisión cuando el proceso de conseguir un trabajo duro.

Yo prefiero el rel="nofollow Boost temporizador biblioteca para su simplicidad, pero si usted no desea utilizar las bibliotecas de tercera parrty, utilizando el reloj () parece razonable.

Como una actualización, parece que el reloj de Windows () mide el tiempo de reloj de pared (con una precisión CLOCKS_PER_SEC)

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

, mientras que en Linux se mide el tiempo de la CPU a través de núcleos utilizados por el proceso actual

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

y (lo que parece, y como se ha señalado por su creador original) en realidad con menor CLOCKS_PER_SEC precisión que, aunque tal vez esto depende de la versión específica de Linux.

Me gusta el método Hola Soy de no utilizar gettimeofday (). A mí me pasó en un servidor que ejecuta el administrador cambia la zona horaria. El reloj se actualiza para mostrar el mismo valor local (correcto). Esto hizo que el tiempo () y gettimeofday () para cambiar 2 horas y todas las marcas de tiempo en algunos servicios se quedó atascado.

escribí una clase C++ usando timeb.

#include <sys/timeb.h>
class msTimer 
{
public:
    msTimer();
    void restart();
    float elapsedMs();
private:
    timeb t_start;
};

Las funciones miembro:

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 <cstdlib>
#include <iostream>

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;
}

Salida en mi equipo es '19'. Precisión de la clase msTimer es del orden de milisegundos. En el ejemplo de uso anterior, el tiempo total de ejecución ocupado por el for de bucle se realiza un seguimiento. Esta vez incluido el sistema operativo de conmutación dentro y fuera del contexto de ejecución de main() debido a la multitarea.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top