¿Cómo utilizar QueryPerformanceCounter?

Resuelto Anonymous asked hace 14 años • 4 respuestas

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::Posixque 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 startingTicksvariable 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.

Anonymous avatar Nov 16 '09 06:11 Anonymous
Aceptado
#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 CounterStartvariable. 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.

Ramónster avatar Nov 15 '2009 23:11 Ramónster

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
 avatar Apr 10 '2013 13:04