C ++ obtenção de tempo milissegundos em Linux - não relógio () parece não funcionar corretamente

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

  •  09-09-2019
  •  | 
  •  

Pergunta

No Windows, clock() retorna o tempo em milissegundos, mas nesta Linux caixa que eu estou trabalhando, arredonda-lo para os 1000 mais próximo assim que a precisão é apenas para o nível de "segunda" e não ao nível milissegundos.

Eu encontrei uma solução com Qt usando a classe QTime, instanciar um objeto e chamando start() sobre ele, então chamando elapsed() para obter o número de milissegundos decorrido.

Eu tenho tipo de sorte, porque eu estou trabalhando com Qt para começar, mas eu gostaria de uma solução que não depende de bibliotecas de terceiros,

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

Atualizar

Por favor, não recomendamos impulso ..

Se Boost e Qt pode fazê-lo, certamente não é mágica, deve haver padrão algo que eles estão usando!

Foi útil?

Solução

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

struct timeval {
  time_t tv_sec;
  suseconds_t tv_usec;
}

Outras dicas

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

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

Ele produz no meu sistema

$ difference: 0

Porque tudo que fizemos foi dormir e não usando qualquer momento CPU! No entanto, usando gettimeofday nós conseguimos o 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;
}

Saídas no meu sistema

$ difference: 5

Se precisar de mais precisão, mas deseja obter tempo de CPU , então você pode considerar o uso da função getrusage.

Eu também recomendo as ferramentas oferecidas pelo Boost. Ou o mencionado impulso Timer, ou cortar alguma coisa fora do Boost.DateTime ou se houver nova biblioteca propostas no sandbox - Boost.Chrono : Este último será um substituto para o temporizador e recurso vontade:

  • utilitários da hora da biblioteca padrão 0x C ++, incluindo:
    • classe de modelo duration
    • classe de modelo time_point
    • Clocks:
      • system_clock
      • monotonic_clock
      • high_resolution_clock
  • modelo de classe timer, com typedefs:
    • system_timer
    • monotonic_timer
    • high_resolution_timer
  • relógios de processo e temporizadores:
    • process_clock, capturando real, user-CPU e sistema de CPU vezes.
    • process_timer, capturando decorrido real, user-CPU, e os tempos de sistema de CPU.
    • run_timer, relatórios conveniente de | process_timer | resultados.
  • em tempo de compilação aritmética racional da biblioteca padrão C ++ 0x.

Aqui está a fonte da lista de recursos

Eu escrevi uma classe Timer baseado em o CTT resposta . Ele 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 <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);
    }
};

Se você não precisa o código para ser portátil para Unices antigos, você pode usar clock_gettime (), que lhe dará o tempo em nanossegundos (se os seus suportes de processador que a resolução). É POSIX, mas a partir de 2001.

relógio () tem um muitas vezes uma resolução muito ruim. Se você quiser medir o tempo no nível de milissegundo, uma alternativa é o uso clock_gettime (), como explicou nesta questão.

(Lembre-se que você precisa para ligação com -lrt no Linux).

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

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

Output:

Delta t2-t1: 3 milliseconds

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

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

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

Sim ... executá-lo duas vezes e subtrair ...

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

gettimeofday - o problema é que podem ter valores mais baixos se você mudar você relógio de hardware (com NTP, por exemplo) Boost - não disponível para este projecto relógio () -. normalmente retorna um número inteiro de 4 bytes, wich significa que a sua fraca capacidade, e depois de algum tempo que retorna números negativos

Eu prefiro criar meu próprio classe e atualizar a cada 10 milissegundos, de modo que este caminho é mais flexível, e posso até mesmo melhorá-lo 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á-la 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); 
.....

Olhe para setitimer eo ITIMER_VIRTUAL e ITIMER_REAL.

Não use o alarme ou UAlarm funções, você terá baixa precisão quando seu processo de obter um trabalho duro.

Eu prefiro o impulso biblioteca temporizador para sua simplicidade, mas se você não quiser usar bibliotecas terço Parrty, usando relógio () parece razoável.

Como uma atualização, parece que no relógio do Windows () medidas de tempo relógio de parede (com precisão CLOCKS_PER_SEC)

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

enquanto no Linux ele mede o tempo de CPU através núcleos usados ??pelo processo atual

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

e (ao que parece, e como observou o cartaz original) realmente com menos precisão do que CLOCKS_PER_SEC, embora talvez isso depende da versão específica do Linux.

Eu gosto do método Hola Soy de não usar gettimeofday (). Aconteceu-me em um servidor executando o administrador alterou o fuso horário. O relógio foi atualizado para mostrar o mesmo valor local (correto). Isso fez com que o tempo function () e gettimeofday () para mudar 2 horas e todas as marcas de tempo em alguns serviços ficou preso.

Eu escrevi uma classe C++ usando timeb.

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

As 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 utilização:

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

Saída no meu computador é '19'. Precisão da classe msTimer é da ordem de milissegundos. No exemplo de uso acima, o tempo total de execução retomado pelo for-ciclo é monitorado. Desta vez incluiu o sistema operacional mudar dentro e fora do contexto de execução de main() devido à multitarefa.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top