Estou tentando fazer isso usando dois FILETIMEs, convertendo-os para ULONGLONGs, subtraindo os ULONGLONGs e dividindo o resultado por 10000. Mas é bem lento e quero saber se existe uma maneira melhor de fazer isso.Eu uso c ++ com o visual studio 2008 express edition. Isto é o que estou usando:
FILETIME filetime,filetime2;
GetSystemTimeAsFileTime(&filetime);
Sleep(100);
GetSystemTimeAsFileTime(&filetime2);
ULONGLONG time1,time2;
time1 = (((ULONGLONG) filetime.dwHighDateTime) << 32) + filetime.dwLowDateTime;
time2 = (((ULONGLONG) filetime2.dwHighDateTime) << 32) + filetime2.dwLowDateTime;
printf("ELAPSED TIME IN MS:%d",(int)((time2-time1)/10000));
Sleep(100)
no seu código. Não tem nada a ver com os temporizadores.Geralmente, timeGetTime () é melhor para a lógica do jogo de temporização - GetTickCount não possui resolução suficientemente alta e QPC e RDTSC são muito mais problemas do que valem para esse fim.
Por outro lado, para criação de perfil, RDTSC ou QPC pode valer a pena. Eu prefiro RDTSC sobre QPC, embora a Microsoft recomende QPC.
As quatro funções de tempo comuns que eu uso no win32:
GetTickCount () retorna o tempo atual em milissegundos em relação a algum zero arbitrário (geralmente, embora nem sempre o tempo de inicialização do sistema), como um número inteiro de 32 bits (para que ocorra a cada 49 dias). Geralmente é o método mais rápido para medir um tempo. Infelizmente, é de baixa resolução - geralmente atualiza apenas 64 vezes por segundo. Ao contrário do boato popular, chamar timeBeginPeriod (1) não aumentará sua resolução em nenhum sistema que eu tenha testado. Há também uma variante de 64 bits, se você estiver preocupado com a quebra.
timeGetTime () retorna o tempo atual, em milissegundos, relativo a algum zero arbitrário, como um valor de 32 bits (para que ocorra após 49 dias ou mais). Não é tão rápido quanto GetTickCount, mas ainda é bastante razoável. Pode ser preciso em um único milissegundo, embora isso possa exigir a chamada timeBeginPeriod (1) primeiro. O uso do timeGetTime requer a vinculação ao winmm.lib e a inclusão do Mmsystem.h.
QueryPerformanceCounter () retorna o horário atual em unidades arbitrárias como um número inteiro de 64 bits. Você pode descobrir quais são as unidades chamando QueryPerformanceFrequency () e as unidades não serão alteradas (na ausência de uma reinicialização). A implementação subjacente disso varia muito, e cada implementação possui suas próprias peculiaridades e erros que podem ocorrer em algum hardware, tornando isso desagradável para uso em aplicativos amplamente implantados. Algumas implementações são muito lentas, outras são razoáveis, embora nenhuma seja tão rápida quanto GetTickCount ou mesmo timeGetTime. Normalmente, a resolução de tempo é melhor que 1 microssegundo, embora não necessariamente muito melhor.
RDTSC é um código de operação da linguagem assembly x86 / x64 que retorna o tempo atual em unidades de ciclos da CPU (ou seja, como um número inteiro de 64 bits. Em alguns compiladores, ele pode ser acessado como um intrínseco (__rdstc), em outros você precisará de asm inline. Sua velocidade varia um pouco entre as CPUs, mas geralmente é bastante razoável - geralmente significativamente mais rápida que QueryPerformanceCounter, mas não tão rápida quanto GetTickCount.Infelizmente, existem algumas peculiaridades - não tantas quanto QueryPerformanceCounter, mas ainda muito mais que as funções de tempo de resolução mais baixa. Às vezes, pode ser executado em versões anteriores em CPUs multicore quando você alterna núcleos devido à sincronização imperfeita entre os núcleos, as unidades são difíceis de descobrir e as unidades podem mudar no meio do tempo devido ao gerenciamento de energia alterando a taxa do clock da CPU.
Observe que cada um desses quatro métodos pode ser desviado em relação aos outros três - não há um fluxo de tempo claro e autorizado.
fonte
Para responder à sua pergunta: não há "melhor" solução para medir o tempo. Todo método tem suas próprias vantagens / desvantagens. Tudo depende de suas necessidades.
Aqui estão várias perguntas que você deve se perguntar antes de escolher uma solução:
resolução do temporizador . Você realmente precisa de um cronômetro preciso (<1ms) ou pode viver com algo menos preciso (por exemplo: precisão de 10ms)?
custo da CPU . alguns métodos exigirão mais CPU do que outros. temporizadores geralmente mais precisos requerem mais CPU. Além disso, a chamada de alguns métodos pode ter consequências para outras aplicações (por exemplo: a chamada
timeBeginPeriod(1)
no win32 estressa o sistema operacional e reduz a vida da bateria do laptop)trabalha com SMP . alguns métodos usam dados específicos da CPU (por exemplo: número de ciclos decorridos) e podem ter alguns problemas em ambientes com multiprocessadores.
funciona com CPU com recurso de economia de energia. Algumas CPUs têm a capacidade de alterar a frequência ao longo do tempo, o que pode causar alguns problemas em alguns métodos de temporização.
Para o exemplo que você dá, eu usaria uma combinação de
QueryPerformanceCounter() / QueryPerformanceFrequency()
.Observe também que no exemplo que você dá,
sleep(100)
na verdade, pode esperar mais de 100 ms. Assim, mesmo com um timer muito preciso, ele pode retornar alguns resultados além de 100ms.fonte
max
chamada com o valor retornado anteriormente.clock_gettime
, são todos especificados para não serem executados de maneira inversa, mesmo em sistemas SMP, e independentemente da frequência atual da CPU. Portanto, é um mau conselho alertar as pessoas para longe delas e para funções de temporização piores, porque qualquer outra função de temporização provavelmente sofreria os mesmos problemas se você conseguisse fazê-las funcionar com a precisão que você queria da QPC em primeiro lugar. Então, sim, há é uma melhor solução: QPC, clock_gettime e mach_absolute_time. Para o tempo de loop do jogo, não há razão para usar qualquer outra coisa, se disponível.Acabei de fazer alguns benchmarks e praticamente não há mais uma boa razão para usar o timeGetTime. QueryPerformanceCounter é um pouco mais rápido e muito mais preciso.
Depois, há GetTickCount, que é quase instantâneo, pois tudo o que faz é reler algum valor que o sistema operacional altera durante o agendamento do processo. O valor permanece o mesmo por mais de 15ms por vez e não é recomendado para nada além de um tempo muito grosseiro.
fonte
Dê uma olhada na função GetTickCount () , seu valor de retorno é o número de milissegundos decorridos desde que o sistema foi iniciado.
fonte