¿Cómo utilizar QueryPerformanceCounter?
Recientemente decidí que necesitaba cambiar el uso de milisegundos a microsegundos para mi clase de Temporizador y, después de investigar un poco, decidí que QueryPerformanceCounter es probablemente mi apuesta más segura. (La advertencia de Boost::Posix
que es posible que no funcione en la API de Win32 me desanimó un poco). Sin embargo, no estoy muy seguro de cómo implementarlo.
Lo que estoy haciendo es llamar a cualquier GetTicks()
función esque que esté usando y asignarla a la startingTicks
variable del temporizador. Luego, para encontrar la cantidad de tiempo transcurrido, simplemente resto el valor de retorno de la función del startingTicks
, y cuando reinicio el temporizador, simplemente llamo a la función nuevamente y le asigno StartingTicks. Desafortunadamente, según el código que he visto, no es tan simple como simplemente llamar QueryPerformanceCounter()
y no estoy seguro de qué se supone que debo pasar como argumento.
#include <windows.h>
double PCFreq = 0.0;
__int64 CounterStart = 0;
void StartCounter()
{
LARGE_INTEGER li;
if(!QueryPerformanceFrequency(&li))
cout << "QueryPerformanceFrequency failed!\n";
PCFreq = double(li.QuadPart)/1000.0;
QueryPerformanceCounter(&li);
CounterStart = li.QuadPart;
}
double GetCounter()
{
LARGE_INTEGER li;
QueryPerformanceCounter(&li);
return double(li.QuadPart-CounterStart)/PCFreq;
}
int main()
{
StartCounter();
Sleep(1000);
cout << GetCounter() <<"\n";
return 0;
}
Este programa debería generar un número cercano a 1000 (la suspensión de Windows no es tan precisa, pero debería ser como 999).
La StartCounter()
función registra el número de ticks que tiene el contador de rendimiento en la CounterStart
variable. La GetCounter()
función devuelve el número de milisegundos desde que StartCounter()
se llamó por última vez como doble, por lo que si GetCounter()
devuelve 0,001, entonces ha pasado aproximadamente 1 microsegundo desde que StartCounter()
se llamó.
Si desea que el temporizador use segundos, cambie
PCFreq = double(li.QuadPart)/1000.0;
a
PCFreq = double(li.QuadPart);
o si quieres microsegundos entonces usa
PCFreq = double(li.QuadPart)/1000000.0;
Pero en realidad se trata de conveniencia ya que devuelve un doble.
Yo uso estas definiciones:
/** Use to init the clock */
#define TIMER_INIT \
LARGE_INTEGER frequency; \
LARGE_INTEGER t1,t2; \
double elapsedTime; \
QueryPerformanceFrequency(&frequency);
/** Use to start the performance timer */
#define TIMER_START QueryPerformanceCounter(&t1);
/** Use to stop the performance timer and output the result to the standard stream. Less verbose than \c TIMER_STOP_VERBOSE */
#define TIMER_STOP \
QueryPerformanceCounter(&t2); \
elapsedTime=(float)(t2.QuadPart-t1.QuadPart)/frequency.QuadPart; \
std::wcout<<elapsedTime<<L" sec"<<endl;
Uso (paréntesis para evitar redefiniciones):
TIMER_INIT
{
TIMER_START
Sleep(1000);
TIMER_STOP
}
{
TIMER_START
Sleep(1234);
TIMER_STOP
}
Resultado del ejemplo de uso:
1.00003 sec
1.23407 sec