Public Group

# QueryPerformanceCounter problems

This topic is 4892 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I'm sorry to post this but after looking on google I just can't get QueryPerformanceCounter to give me the number of seconds past. I need it for my pac-man game and using clock() for timebased movement does not work too well. I have a bit of code which does not work. I want to be able to multiple the seconds by a number of how many pixels to move a second so thats what they move by. So if it is 50 pixels a second and .1 seconds elapsed move 5 pixels. But I can't get this to work. Here is my code
#include <windows.h>
#include <ctime>
#include <cstdlib>
#include <stdio.h>
#include <iostream>

LARGE_INTEGER GetElapsedTime(LARGE_INTEGER start)
{
LARGE_INTEGER ticspersecond;				//The cpu speed, needed to work out how many tics/sec
LARGE_INTEGER time1, time2;				//The 1st and 2nd time to work out the difference between the 2
float tics;						//A more convinent place to store ticspersecond
float difference;					//The ticks between the 1st and 2nd time
float seconds;						//The time in seconds between the 1st and 2nd time

QueryPerformanceFrequency (&ticspersecond);		//WINAPI funciton, Gets the ticks per second
tics = ticspersecond.QuadPart;				//A more convinent place to store ticspersecond, optional
QueryPerformanceCounter (&start);			//WINAPI funciton, Gets the 1st time
return start;
}

int main()
{
LARGE_INTEGER LastUpdate = GetElapsedTime(LastUpdate);
LARGE_INTEGER CurrentTime = GetElapsedTime(CurrentTime);

{
CurrentTime = GetElapsedTime(CurrentTime);   // Update counter
LastUpdate = GetElapsedTime(LastUpdate);   // Update counter
}
return 0;
}


Can someone point out what I am doing wrong please? Thanks vbuser

##### Share on other sites
Try something like this:

1. You need to get the resolution of your motherboards high performance counter and check one actually exists (should do on most new systems). The code below should give you starting time:

LARGE_INTEGER startTime;
LARGE_INTEGER lastTime;
LARGE_INTEGER currentTime;

if (QueryPerformanceCounter((LARGE_INTEGER *)&startTime))
{
QueryPerformanceFrequency((LARGE_INTEGER *)&frequency);
}
else
{
printf("ERROR: QueryPerformanceCounter not available on this machine \n");
}

startTick = GetTickCount();

//Get the current Performance Counter value
QueryPerformanceCounter((LARGE_INTEGER *)¤tTime);

elapsedTimeError = 0.0;

// Store last time and tick
lastTick = startTick;

firstTime = true;

2. To get the elapsed time:

// Get QUERYCount method
double previousError;
DWORD deltaPerformanceCounter;
DWORD deltaTickCount;

//Store the last tick count
lastTick = currentTick;

//get the current tick count
currentTick = GetTickCount();

//Store the elapsed tick count from the startTick
elapsedTick = currentTick - startTick;

//Store the last Time

//Get the current Performance Counter value
QueryPerformanceCounter((LARGE_INTEGER *)¤tTime);

// Calculate the elapsed time in secs from the start time
//printf("Elapsed Time %f\n",elapsedTime) ;

// First time do not check for jumps as there will be a big jump!
if (!firstTime)
{
deltaTickCount = currentTick - lastTick;
previousError = elapsedTimeError ;

// if differnce between performance counter and tick count methods
// is greater than 500 ms then Counter has jumped
if ( abs( deltaPerformanceCounter - deltaTickCount ) > 500)
{
// printf("Timer jump\n");
elapsedTimeError = elapsedTimeError + (double)( (deltaPerformanceCounter/1000.0) - (deltaTickCount/1000.0) );
elapsedTime = elapsedTime - elapsedTimeError + previousError;
}
}
firstTime=false;

3. The elapsedTime should contain the number of seconds that have passed to however many decimal places your timer supports:

I hope this helps. If not, let me know and I'll try to explain it a bit better.

Mr. Creamy.

BTW: Just in case you are not aware, LARGE_INTEGER is defined somewhere in one of the headers window.h references.

##### Share on other sites
I'm not exactly sure what you're trying to do in GetElapsedTime().

Some ideas:

You probably just want to call QueryPerformanceFrequency() once in your program.

The QPFrequency should be a divisor, not a multiplier.

I don't see any place where you subtract time2 from time1. In fact a lot of your variables and headers go unused, but you're definately going to need to subtract two tick counts at some point. That part of the logic is essential.

Finally, I've got a CTimer class that uses QPC if available, and if not, uses timGetTime(). I can post that code if you want - it's only about a hundred lines in total (header plus source).

Hope that helps.

##### Share on other sites
1. seconds = ticks / ticks_per_second.

2. You can't use floats when converting to seconds. floats don't have enough precision to hold the values returned by QPC and QPF. Furthermore, you have to be careful because doubles don't have enough precision to hold values values returned by QPC. You should do it like this:
    double elapsed_seconds = double( current_time - old_time ) / double( ticks_per_second );

##### Share on other sites
Ok I got this code working I'm pretty sure right. But I would be interested at looking at your timer class if you didn't mind. Well here is what I have
#include <windows.h>#include <iostream>int main(){    LARGE_INTEGER startTime;    LARGE_INTEGER lastTime;    LARGE_INTEGER currentTime; 	LARGE_INTEGER frequency;	LARGE_INTEGER elaspedTime;	    if (QueryPerformanceCounter((LARGE_INTEGER *)&startTime))    {        QueryPerformanceFrequency((LARGE_INTEGER *)&frequency);    }    else    {        std::cout << "ERROR: QueryPerformanceCounter not available on this machine \n";    }    QueryPerformanceCounter(&currentTime);        //Get the current Performance Counter value    QueryPerformanceCounter(&startTime);	char answer = 'y';	while(answer == 'y')	{        QueryPerformanceCounter(&currentTime);        double timedif = double(((currentTime.QuadPart - lastTime.QuadPart) * 1000) / frequency.QuadPart) / 1000;        QueryPerformanceCounter(&lastTime);                std::cout << timedif << std::endl;        std::cin >> answer;    }	return 0;}

Thanks for the help with this.
vbuser

##### Share on other sites
The "* 1000" and "/ 1000" will result in a 1 ms resolution, which is ok. But if you use a floating-point divide (with doubles) you will get the full resolution.
    double timedif = double(currentTime.QuadPart - lastTime.QuadPart) / double(frequency.QuadPart);
Also, instead of querying the time twice, you can simply copy it ("lastTime = currentTime;"). Not only is this faster, but when you query the time twice, your elapsed time is slightly off.

##### Share on other sites
Thanks. I fixed those two things now I just have to add a few more things and some levels and it will be done. Hopefully it won't take me too long.
Cya later,
vbuser

1. 1
Rutin
32
2. 2
3. 3
4. 4
5. 5

• 13
• 69
• 11
• 10
• 14
• ### Forum Statistics

• Total Topics
632967
• Total Posts
3009570
• ### Who's Online (See full list)

There are no registered users currently online

×