c++ - Medição de tempo no Windows - Stack Overflow em Português
Gostaria de saber qual a melhor forma de medir o tempo de execução de um programa em C++. Encontrei diversas soluções na internet, cada uma com uma abordagem. Sugestões?
perguntada 16/03/14 às 1:53
Para Windows especificamente, a melhor forma (no sentido de possuir maior resolução) é usar o QueryPerformanceCounter.
Um exemplo do uso (use um compilador recente):
mPCFreq = static_cast<double>(li.QuadPart)/1000.0;
mCounterStart = li.QuadPart;
// Retorna o tempo em milisegundos desde que o
// objeto Watch foi criado.
return static_cast<double>(li.QuadPart - mCounterStart)/mPCFreq;
uint64_t mCounterStart;
double mPCFreq;
Watch counter;
std::cout << counter.getCounter() << std::endl;
Nesse caso, o código retorna o tempo em milissegundos entre a criação do objeto Watch e a chamada counter.getCounter().
Outra solução mais portável é usar a biblioteca boost e usar boost::posix_time::time_duration para medir o tempo na escala que você desejar (milisegundos, microsegundos, segundos).
editada 16/03/14 às 2:59
respondida 16/03/14 às 2:33
Algumas recomendações: 1. Sempre que possível (isto é, se o compilador suportar), deve-se usar os tipos em stdint.h, como int64, em vez de __int64. 2. Devem-se evitar usar variáveis globais para este tipo de coisa. Fazer CounterStart uma variável local e passá-la para o main com um return e para o GetCounter como argumento seria melhor. – luiscubal 16/03/14 às 2:44
@luiscubal Fiz umas alterações no código. É uma abordagem diferente. O que acha? – Lucas Lima 16/03/14 às 3:01
Bem melhor, embora o cout no construtor não seja ideal (uma exceção seria preferível). Já agora, em caso de erro, é possível obter uma mensagem mais detalhada com GetLastError e FormatMessage com FORMAT_MESSAGE_FROM_SYSTEM. – luiscubal 16/03/14 às 3:08
@luiscubal, de acordo com a documentação das funções, versões posteriores ao XP não causarão erro ao invocar essa função da API. O código está OK então. – user6635 16/03/14 às 14:54
@lfelix O QueryPerformanceCounter é chamado uma vez só no contrutor. O outro, que você deve ter confundido, é o QueryPerformanceFrequency, que obtém a frequência. – Lucas Lima 16/03/14 às 15:01
C++11 provê high_resolution_clock, é a solução ideal porém a microsoft ainda não provê uma implementação correta que use QueryPerformanceCounter. Isto é considerado um bug, e parece que será resolvido na próxima versão do visual studio. Portanto no momento melhor usar QueryPerformanceCounter diretamente ou uma biblioteca cuja implementação use.
editada 16/03/14 às 4:48
respondida 16/03/14 às 4:42
Utilizar o QueryPerformanceCounter do MingW pode resolver esse problema? – user6635 16/03/14 às 14:15
@lfelix o QueryPerformanceCounter do MinGW dever ser o mesmo do nativo Windows. – pepper_chico 16/03/14 às 15:06
O texto(Optimizing software in C++ - recomendo ler) mostra como podemos alcançar isso.
As medidas de tempo podem requerer uma resolução muito alta, se os intervalos de tempo são curtas. No Windows, você pode usar as funções GetTickCount ou QueryPerformanceCounter para resolução de milissegundos. A resolução muito maior pode ser obtido com o contador de carimbo de tempo na CPU, que conta com a freqüência do relógio da CPU.
Há um problema que a frequência do relógio pode variar de forma dinâmica e que as medições são instáveis ​​devido a interrupções e switches da tarefa.
É interessante olhar também para a classe StopWatch que é baseada em duas API's, a QueryPerformanceFrequency e QueryPerformanceCounter.