C ++ obter milissegundos de tempo no Linux – relógio () não parece funcionar corretamente

No Windows, clock() retorna o tempo em milissegundos, mas nesta checkbox do Linux em que estou trabalhando, ele é arredondado para o 1000 mais próximo, então a precisão é apenas para o nível “segundo” e não para o nível de milissegundos.

Eu encontrei uma solução com o Qt usando a class QTime , instanciando um object e chamando start() e então chamando elapsed() para obter o número de milissegundos decorridos.

Eu tive sorte porque estou trabalhando com o Qt para começar, mas gostaria de uma solução que não dependa de bibliotecas de terceiros,

Não há uma maneira padrão de fazer isso?

ATUALIZAR

Por favor, não recomendo o Boost ..

Se Boost e Qt podem fazer isso, certamente não é mágica, deve haver algo padrão que eles estão usando!

Você pode usar gettimeofday no início e no final de seu método e, em seguida, diferenciar as duas estruturas de retorno. Você terá uma estrutura como a seguinte:

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

Por favor, note que o clock não mede a hora do relógio de parede. Isso significa que se o seu programa levar 5 segundos, o clock não medirá necessariamente 5 segundos, mas poderia mais (seu programa poderia executar vários threads e assim consumir mais CPU do que tempo real) ou menos. Mede uma aproximação do tempo de CPU usado. Para ver a diferença, 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; } 

Ele sai no meu sistema

 $ difference: 0 

Porque tudo o que fizemos foi dormir e não usar nenhum tempo de CPU! No entanto, usando gettimeofday , conseguimos o 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; } 

Saídas no meu sistema

 $ difference: 5 

Se você precisar de mais precisão, mas quiser obter tempo de CPU , considere o uso da function getrusage .

Eu também recomendo as ferramentas oferecidas pelo Boost. Ou o Boost Timer mencionado, ou hackear algo de Boost.DateTime ou há uma nova biblioteca proposta no sandbox – Boost.Crono : Este último será um substituto para o Timer e contará com:

  • Utilitários de tempo do C ++ 0x Standard Library, incluindo:
    • duration modelo de class
    • Modelo de class time_point
    • Relógios:
      • system_clock
      • monotonic_clock
      • high_resolution_clock
  • timer modelo de class, com typedefs:
    • system_timer
    • monotonic_timer
    • high_resolution_timer
  • Processar relógios e timeres:
    • process_clock , capturando os tempos reais, da CPU do usuário e da CPU do sistema.
    • process_timer , capturando os tempos reais, CPU do usuário e CPU do sistema.
    • run_timer , relatórios convenientes de | process_timer | resultados.
  • A aritmética racional de tempo de compilation da biblioteca padrão do C ++ 0x.

Aqui está a fonte da lista de resources

Eu escrevi uma aula de Timer base na resposta da CTT . Pode ser usado da seguinte maneira:

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

Aqui está a sua implementação:

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

Se você não precisa que o código seja portável para os antigos, você pode usar o clock_gettime (), que lhe dará o tempo em nanossegundos (se o seu processador suportar essa resolução). É POSIX, mas a partir de 2001.

clock () tem frequentemente uma resolução muito ruim. Se você quiser medir o tempo no nível de milissegundos, uma alternativa é usar clock_gettime (), conforme explicado nesta pergunta.

(Lembre-se de que você precisa vincular -lrt no Linux).

Com C ++ 11 e std::chrono::high_resolution_clock você pode fazer isso:

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

Saída:

 Delta t2-t1: 3 milliseconds 

Link para demonstração: http://cpp.sh/2zdtu

clock () não retorna milissegundos ou segundos no linux. Normalmente clock () retorna microssegundos em um sistema linux. A maneira correta de interpretar o valor retornado por clock () é dividi-lo por CLOCKS_PER_SEC para descobrir quanto tempo passou.

Isso deve funcionar … testado em um 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); } 

Sim … corra duas vezes e subtraia …

No clock padrão POSIX, seu valor de retorno é definido em termos do símbolo CLOCKS_PER_SEC e uma implementação é livre para definir isso de qualquer maneira conveniente. No Linux, tive boa sorte com a function times() .

gettimeofday – o problema é que pode ter valores menores se você alterar seu relógio de hardware (com NTP, por exemplo) Boost – não disponível para este relógio de projeto () – geralmente retorna um inteiro de 4 bytes, o que significa que é uma capacidade baixa, e depois de algum tempo, ele retorna números negativos.

Eu prefiro criar minha própria class e atualizar cada 10 milissegundos, então é mais flexível, e posso até melhorar para ter assinantes.

 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 atualizá-lo eu 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); ..... 

Veja o setitimer e o ITIMER_VIRTUAL e o ITIMER_REAL.

Não use as funções de alarme ou ualarme, você terá baixa precisão quando o seu processo começar um trabalho árduo.

Eu prefiro a biblioteca Boost Timer por sua simplicidade, mas se você não quer usar bibliotecas de terceiros, usar clock () parece razoável.

Como atualização, aparece que no relógio do Windows () mede a hora do relógio de parede (com precisão CLOCKS_PER_SEC)

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

enquanto no Linux mede o tempo de CPU nos núcleos usados ​​pelo processo atual

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

e (parece, e como observado pelo autor original), na verdade, com menos precisão do que CLOCKS_PER_SEC, embora talvez isso dependa da versão específica do Linux.

Eu gosto do método Hola Soy de não usar gettimeofday (). Aconteceu comigo em um servidor em execução, o administrador mudou o fuso horário. O relógio foi atualizado para mostrar o mesmo valor local (correto). Isso causou o tempo de function () e gettimeofday () para mudar de 2 horas e todos os carimbos de hora em alguns serviços ficaram presos.

Eu escrevi uma class C++ usando o timeb .

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

Funções de membro:

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

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

Saída no meu computador é '19'. A precisão da class msTimer é da ordem de milissegundos. No exemplo de uso acima, o tempo total de execução assumido pelo for -loop é rastreado. Desta vez incluiu o sistema operacional comutando e expirando o contexto de execução de main() devido à multitarefa.