Meça facilmente o tempo decorrido

Eu estou tentando usar o tempo () para medir vários pontos do meu programa.

O que não entendo é por que os valores no antes e no depois são os mesmos? Eu entendo que esta não é a melhor maneira de criar o perfil do meu programa, eu só quero ver quanto tempo leva algo.

printf("**MyProgram::before time= %ld\n", time(NULL)); doSomthing(); doSomthingLong(); printf("**MyProgram::after time= %ld\n", time(NULL)); 

Eu tentei:

 struct timeval diff, startTV, endTV; gettimeofday(&startTV, NULL); doSomething(); doSomethingLong(); gettimeofday(&endTV, NULL); timersub(&endTV, &startTV, &diff); printf("**time taken = %ld %ld\n", diff.tv_sec, diff.tv_usec); 

Como leio um resultado do **time taken = 0 26339 ? Isso significa 26.339 nanossegundos = 26,3 ms?

Que tal **time taken = 4 45025 , isso significa 4 segundos e 25 ms?

   
 #include  void f() { using namespace std; clock_t begin = clock(); code_to_time(); clock_t end = clock(); double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC; } 

A function time() só é precisa dentro de um segundo, mas há CLOCKS_PER_SEC “relógios” dentro de um segundo. Essa é uma medida fácil e portátil, embora seja simplificada demais.

Você pode abstrair o mecanismo de medição de tempo e ter o tempo de execução de cada chamada medido com o mínimo de código extra , apenas sendo chamado através de uma estrutura de timer. Além disso, em tempo de compilation você pode parametrizar o tipo de tempo (milissegundos, nanossegundos etc).

Graças à revisão de Loki Astari e à sugestão de usar modelos variadic. É por isso que a chamada de function encaminhada.

 #include  #include  template struct measure { template static typename TimeT::rep execution(F&& func, Args&&... args) { auto start = std::chrono::steady_clock::now(); std::forward(func)(std::forward(args)...); auto duration = std::chrono::duration_cast< TimeT> (std::chrono::steady_clock::now() - start); return duration.count(); } }; int main() { std::cout < < measure<>::execution(functor(dummy)) < < std::endl; } 

Demonstração

De acordo com o comentário de Howard Hinnant , é melhor não fugir do sistema crono até que tenhamos de fazê-lo. Portanto, a class acima poderia dar ao usuário a opção de chamar a count manualmente, fornecendo um método extra estático (mostrado em C ++ 14)

 template static auto duration(F&& func, Args&&... args) { auto start = std::chrono::steady_clock::now(); std::forward(func)(std::forward(args)...); return std::chrono::duration_cast(std::chrono::steady_clock::now()-start); } // call .count() manually later when needed (eg IO) auto avg = (measure<>::duration(func) + measure<>::duration(func)) / 2.0; 

e ser mais útil para clientes que

"quer pós-processar um monte de durações antes da E / S (por exemplo, média)"


O código completo pode ser encontrado aqui . Minha tentativa de construir uma ferramenta de benchmarking baseada no cronógrafo é registrada aqui .


Se o std::invoke do C ++ 17 estiver disponível, a invocação do callable em execution poderia ser feita assim:

 invoke(forward(func), forward(args)...); 

para fornecer callables que são pointers para funções de membro.

 //***C++11 Style:*** std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); std::chrono::steady_clock::time_point end= std::chrono::steady_clock::now(); std::cout < < "Time difference = " << std::chrono::duration_cast(end - begin).count() < 
		      	

Como eu posso ver na sua pergunta, parece que você quer saber o tempo decorrido após a execução de algum pedaço de código. Eu acho que você ficaria confortável em ver os resultados em segundo (s). difftime() caso, tente usar a function difftime() conforme mostrado abaixo. Espero que isso resolva seu problema.

 #include  

Apenas Windows: (A tag do Linux foi adicionada depois que postei essa resposta)

Você pode usar GetTickCount () para obter o número de milissegundos decorridos desde que o sistema foi iniciado.

 long int before = GetTickCount(); // Perform time-consuming operation long int after = GetTickCount(); 

a function de hora (NULL) retornará o número de segundos decorridos desde 01/01/1970 às 00:00. E porque, essa function é chamada em horário diferente no seu programa, sempre será diferente Hora em C ++

time(NULL) retorna o número de segundos decorridos desde 01/01/1970 às 00:00 ( o Epoch ). Portanto, a diferença entre os dois valores é o número de segundos que o processamento levou.

 int t0 = time(NULL); doSomthing(); doSomthingLong(); int t1 = time(NULL); printf ("time = %d secs\n", t1 - t0); 

Você pode obter resultados mais getttimeofday() com getttimeofday() , que retorna o tempo atual em segundos, como time() , e também em microssegundos.

 #include

Os valores impressos pelo segundo programa são segundos e microssegundos.

 0 26339 = 0.026'339 s = 26339 µs 4 45025 = 4.045'025 s = 4045025 µs 
 struct profiler { std::string name; std::chrono::high_resolution_clock::time_point p; profiler(std::string const &n) : name(n), p(std::chrono::high_resolution_clock::now()) { } ~profiler() { using dura = std::chrono::duration; auto d = std::chrono::high_resolution_clock::now() - p; std::cout < < name << ": " << std::chrono::duration_cast(d).count() < < std::endl; } }; #define PROFILE_BLOCK(pbn) profiler _pfinstance(pbn) 

O uso está abaixo ::

 { PROFILE_BLOCK("Some time"); // your code or function } 

Isso é semelhante ao RAII no escopo

NOTA isso não é meu, mas eu pensei que era relevante aqui

 #include  #include  #include  #include  #include  using namespace std; using namespace std::chrono; void f1() { high_resolution_clock::time_point t1 = high_resolution_clock::now(); high_resolution_clock::time_point t2 = high_resolution_clock::now(); double dif = duration_cast( t2 - t1 ).count(); printf ("Elasped time is %lf nanoseconds.\n", dif ); } void f2() { timespec ts1,ts2; clock_gettime(CLOCK_REALTIME, &ts1); clock_gettime(CLOCK_REALTIME, &ts2); double dif = double( ts2.tv_nsec - ts1.tv_nsec ); printf ("Elasped time is %lf nanoseconds.\n", dif ); } void f3() { struct timeval t1,t0; gettimeofday(&t0, 0); gettimeofday(&t1, 0); double dif = double( (t1.tv_usec-t0.tv_usec)*1000); printf ("Elasped time is %lf nanoseconds.\n", dif ); } void f4() { high_resolution_clock::time_point t1 , t2; double diff = 0; t1 = high_resolution_clock::now() ; for(int i = 1; i < = 10 ; i++) { t2 = high_resolution_clock::now() ; diff+= duration_cast( t2 - t1 ).count(); t1 = t2; } printf ("high_resolution_clock:: Elasped time is %lf nanoseconds.\n", diff/10 ); } void f5() { timespec ts1,ts2; double diff = 0; clock_gettime(CLOCK_REALTIME, &ts1); for(int i = 1; i < = 10 ; i++) { clock_gettime(CLOCK_REALTIME, &ts2); diff+= double( ts2.tv_nsec - ts1.tv_nsec ); ts1 = ts2; } printf ("clock_gettime:: Elasped time is %lf nanoseconds.\n", diff/10 ); } void f6() { struct timeval t1,t2; double diff = 0; gettimeofday(&t1, 0); for(int i = 1; i <= 10 ; i++) { gettimeofday(&t2, 0); diff+= double( (t2.tv_usec-t1.tv_usec)*1000); t1 = t2; } printf ("gettimeofday:: Elasped time is %lf nanoseconds.\n", diff/10 ); } int main() { // f1(); // f2(); // f3(); f6(); f4(); f5(); return 0; } 

Internamente, a function acessará o relógio do sistema, e é por isso que ele retorna valores diferentes a cada vez que você o chama. Em geral, com linguagens não funcionais, pode haver muitos efeitos colaterais e estados ocultos em funções que você não pode ver apenas observando o nome e os argumentos da function.

A chamada de function de time(NULL) retornará o número de segundos decorridos desde o epoc: 1 de janeiro de 1970. Talvez o que você queira fazer é tirar a diferença entre dois timestamps:

 size_t start = time(NULL); doSomthing(); doSomthingLong(); printf ("**MyProgram::time elapsed= %lds\n", time(NULL) - start); 

Pelo que é visto, tv_sec armazena os segundos decorridos enquanto tv_usec armazena os microssegundos transcorridos separadamente. E eles não são as conversões um do outro. Assim, eles devem ser alterados para a unidade adequada e adicionados para obter o tempo total decorrido.

 struct timeval startTV, endTV; gettimeofday(&startTV, NULL); doSomething(); doSomethingLong(); gettimeofday(&endTV, NULL); printf("**time taken in microseconds = %ld\n", (endTV.tv_sec * 1e6 + endTV.tv_usec - (startTV.tv_sec * 1e6 + startTV.tv_usec)) ); 

No linux, clock_gettime () é uma das boas escolhas. Você deve vincular a biblioteca em tempo real (-lrt).

 #include  #include  #include  #include  

Como outros já observaram, a function time () na biblioteca padrão C não possui uma resolução melhor que um segundo. A única function C totalmente portátil que pode fornecer melhor resolução parece ser clock (), mas que mede o tempo do processador em vez do tempo de clock. Se alguém está satisfeito em se limitar a plataformas POSIX (por exemplo, Linux), então a function clock_gettime () é uma boa escolha.

Desde o C ++ 11, existem instalações de temporização muito melhores disponíveis que oferecem melhor resolução em um formato que deve ser muito portátil em diferentes compiladores e sistemas operacionais. Da mesma forma, a biblioteca boost :: datetime fornece boas classs de tempo de alta resolução que devem ser altamente portáteis.

Um desafio ao usar qualquer um desses resources é o atraso de tempo introduzido pela consulta do relógio do sistema. Da experiência com clock_gettime (), boost :: datetime e std :: chrono, esse atraso pode ser facilmente uma questão de microssegundos. Portanto, ao medir a duração de qualquer parte de seu código, você precisa permitir que haja um erro de medição em torno desse tamanho ou tentar corrigir esse erro zero de alguma forma. Idealmente, você pode querer reunir várias medições do tempo gasto pela sua function e calcular a média ou o tempo máximo / mínimo gasto em várias execuções.

Para ajudar com todos esses problemas de portabilidade e coleta de statistics, desenvolvi a biblioteca cxx-rtimers disponível no Github que tenta fornecer uma API simples para blocos de tempo de código C ++, computando zero erros e reportando statistics de vários timers incorporados no seu código. Se você tem um compilador C ++ 11, basta #include e usar algo como:

 void expensiveFunction() { static rtimers::cxx11::DefaultTimer timer("expensiveFunc"); auto scopedStartStop = timer.scopedStart(); // Do something costly... } 

Na saída do programa, você obterá um resumo das statistics de tempo escritas para std :: cerr como:

 Timer(expensiveFunc):  = 6.65289us, std = 3.91685us, 3.842us < = t <= 63.257us (n=731) 

que mostra o tempo médio, seu desvio-padrão, os limites superior e inferior e o número de vezes que essa function foi chamada.

Se você quiser usar funções de temporização específicas do Linux, você pode #include , ou se você tiver as bibliotecas Boost, mas um compilador C ++ mais antigo, você pode #include . Há também versões dessas classs de timer que podem coletar informações de tempo estatístico de vários threads. Também existem methods que permitem estimar o erro zero associado a duas consultas imediatamente consecutivas do relógio do sistema.

Eles são os mesmos porque a sua function doSomething acontece mais rápido que a granularidade do timer. Experimentar:

 printf ("**MyProgram::before time= %ld\n", time(NULL)); for(i = 0; i < 1000; ++i) { doSomthing(); doSomthingLong(); } printf ("**MyProgram::after time= %ld\n", time(NULL)); 

A razão pela qual ambos os valores são os mesmos é porque seu procedimento longo não leva tanto tempo – menos de um segundo. Você pode tentar apenas adicionar um loop longo (para (int i = 0; i <100000000; i ++);) no final da função para se certificar de que este é o problema, então podemos ir a partir daí ...

No caso de o acima ser verdade, você precisará encontrar uma function de sistema diferente (eu entendo que você trabalha no linux, então eu não posso te ajudar com o nome da function) para medir o tempo com mais precisão. Tenho certeza que existe uma function simular para GetTickCount () no linux, você só precisa encontrá-lo.

Eu costumo usar o seguinte:

 #include  #include  using perf_clock = std::conditional< std::chrono::high_resolution_clock::is_steady, std::chrono::high_resolution_clock, std::chrono::steady_clock >::type; using floating_seconds = std::chrono::duration; template floating_seconds run_test(Func&& func, Args&&... args) { const auto t0 = perf_clock::now(); std::forward(func)(std::forward(args)...); return floating_seconds(perf_clock::now() - t0); } 

É o mesmo que @ nikos-athanasiou proposto, exceto que eu evito o uso de um relógio não estável e uso de número flutuante de segundos como duração.

C ++ std :: chrono tem um claro benefício de ser multi-plataforma. No entanto, também introduz uma sobrecarga significativa em comparação com POSIX clock_gettime (). Na minha checkbox Linux, todos os sabores std::chrono::xxx_clock::now() executam aproximadamente o mesmo:

 std::chrono::system_clock::now() std::chrono::steady_clock::now() std::chrono::high_resolution_clock::now() 

Embora POSIX clock_gettime(CLOCK_MONOTONIC, &time) deva ser o mesmo que steady_clock::now() mas é mais de x3 vezes mais rápido!

Aqui está o meu teste, por completude.

 #include  #include  #include  void print_timediff(const char* prefix, const struct timespec& start, const struct timespec& end) { double milliseconds = (end.tv_nsec - start.tv_nsec) / 1e6 + (end.tv_sec - start.tv_sec) * 1e3; printf("%s: %lf milliseconds\n", prefix, milliseconds); } int main() { int i, n = 1000000; struct timespec start, end; // Test stopwatch clock_gettime(CLOCK_MONOTONIC, &start); for (i = 0; i < n; ++i) { struct timespec dummy; clock_gettime(CLOCK_MONOTONIC, &dummy); } clock_gettime(CLOCK_MONOTONIC, &end); print_timediff("clock_gettime", start, end); // Test chrono system_clock clock_gettime(CLOCK_MONOTONIC, &start); for (i = 0; i < n; ++i) auto dummy = std::chrono::system_clock::now(); clock_gettime(CLOCK_MONOTONIC, &end); print_timediff("chrono::system_clock::now", start, end); // Test chrono steady_clock clock_gettime(CLOCK_MONOTONIC, &start); for (i = 0; i < n; ++i) auto dummy = std::chrono::steady_clock::now(); clock_gettime(CLOCK_MONOTONIC, &end); print_timediff("chrono::steady_clock::now", start, end); // Test chrono high_resolution_clock clock_gettime(CLOCK_MONOTONIC, &start); for (i = 0; i < n; ++i) auto dummy = std::chrono::high_resolution_clock::now(); clock_gettime(CLOCK_MONOTONIC, &end); print_timediff("chrono::high_resolution_clock::now", start, end); return 0; } 

E esta é a saída que recebo quando compilada com gcc7.2-O3:

 clock_gettime: 24.484926 milliseconds chrono::system_clock::now: 85.142108 milliseconds chrono::steady_clock::now: 87.295347 milliseconds chrono::high_resolution_clock::now: 84.437838 milliseconds 

Em resposta às três perguntas específicas do OP .

“O que eu não entendo é porque os valores no antes e no depois são os mesmos?

A primeira pergunta e código de exemplo mostra que time() tem uma resolução de 1 segundo, então a resposta deve ser que as duas funções sejam executadas em menos de 1 segundo. Mas, ocasionalmente, irá (aparentemente de forma ilógica) informar 1 segundo se as duas marcações do timer ocuparem um limite de um segundo.

O próximo exemplo usa gettimeofday() que preenche essa estrutura

 struct timeval { time_t tv_sec; /* seconds */ suseconds_t tv_usec; /* microseconds */ }; 

ea segunda pergunta pergunta: “Como eu leio um resultado de **time taken = 0 26339 ? Isso significa 26.339 nanossegundos = 26,3 ms?”

Minha segunda resposta é que o tempo gasto é de 0 segundos e 26339 microssegundos, ou seja, 0,026339 segundos, o que confirma o primeiro exemplo em execução em menos de 1 segundo.

A terceira questão pergunta: “E quanto ao **time taken = 4 45025 , isso significa 4 segundos e 25 ms?”

Minha terceira resposta é que o tempo gasto é de 4 segundos e 45025 microssegundos, ou seja, 4,045025 segundos, o que mostra que OP alterou as tarefas executadas pelas duas funções que ele programou anteriormente.

Você pode usar a biblioteca SFML , que é Simple and Fast Multimedia Library. Ele inclui muitas classs úteis e bem definidas, como Clock, Socket, Sound, Graphics, etc. É muito fácil de usar e altamente recomendado.

Este é um exemplo para esta questão.

 sf::Clock clock; ... Time time1 = clock.getElapsedTime(); ... Time time2 = clock.restart();