# QueryPerformanceCounter Questions

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

## Recommended Posts

I used to use timeGetTime() but its low resolution was cuasing me some problems. Now im trying to use query performance counter but im running into new problems. Maybe an extra set of eyes can help me spot them. The problem: The programs output is it count of FPS and the frame time. The numbers dont coincide with eachother. I just cant figure out why. Here is the relevant code, I really cant see whats worng even though its probably something simple I've been staring at it for an hour!
    //fps stuff
//start and end_time are used to get the time it takes for one frame.
LARGE_INTEGER timetmp;

__int64 start_time = 0, end_time = 0;
long frame_count = 0;
//sec_e is used to see if a second has passed.
__int64 sec_e = 0;

__int64 second;

QueryPerformanceFrequency(&timetmp);

while((msg.message!=WM_QUIT))
{
QueryPerformanceCounter(&timetmp);     //Begin timing frame

//Do my thing... draw a frame. None of the timing related variable get touched here.

frame_count++;
//And see if a second has elapsed
if(start_time - sec_e > second)
{
// Its been a second so put the number of frames rendered into g_fps and clear the frame counter
g_fps = frame_count;
frame_count = 0;

//Start timing a second again
QueryPerformanceCounter(&timetmp);

//TODO:
if(1) //If fps is being displayed
{
//Display g_fps somewhere
char ss[30];
statstr = "";
sprintf(ss, "FPS: %d FrameTime: %f ms", g_fps, (float)( start_time - end_time));
}
}
QueryPerformanceCounter(&timetmp); //set the frame end time
}


[Edited by - chad_420 on June 1, 2005 3:03:18 AM]

##### Share on other sites
It probably ought to be (end_time - start_time) in the sprintf and then you need to snap end_time prior to the fps code block. Right now I think you're timing the loop overhead.

##### Share on other sites
(end_time - start_time) give me negative numbers... and no I really dont get it either :D but the case is the same for timeGetTime();

edit: you make sense now too lol!

[Edited by - chad_420 on June 1, 2005 3:53:02 AM]

##### Share on other sites
QueryPerformanceCounter() does not return the number of milliseconds, it returns the number of "ticks" elapsed.

What you need to do is divide the number of ticks by the value you recieved from QueryPerformanceFrequency() to determine the number of elapsed seconds, and then multiply that by 1000 to convert to milliseconds.

I took your code and converted it into a simple console application, and simulated frame rendering time with Sleep(rand()%10).
I also added code so that the displayed FrameTime is an average of all the frames within that second, instead of the most recent at the time of fps printing.

Here's the output:
FPS: 192 Avg FrameTime: 5.2191 msFPS: 177 Avg FrameTime: 5.6576 msFPS: 205 Avg FrameTime: 4.8857 msFPS: 200 Avg FrameTime: 5.0177 msFPS: 188 Avg FrameTime: 5.3483 msFPS: 182 Avg FrameTime: 5.5193 ms

And here's the source:
//fps stuff    //start and end_time are used to get the time it takes for one frame.    LARGE_INTEGER timetmp;        __int64 start_time = 0, end_time = 0, frame_time_avg=0;    long frame_count = 0;    long g_fps=0;    __int64 second;    __int64 sec_e=0;        QueryPerformanceFrequency(&timetmp);    second = timetmp.QuadPart;        // get start time BEFORE we enter the loop.    QueryPerformanceCounter(&timetmp);    sec_e = timetmp.QuadPart;        while(true)    {         //start frame timing        QueryPerformanceCounter(&timetmp);        start_time = timetmp.QuadPart;            //Do my thing... draw a frame. None of the timing related variable get touched here.        // simulate a frame        Sleep(rand()%10);        //Advance the frame counter        frame_count++;        // stop frame timing        QueryPerformanceCounter(&timetmp); //set the frame end time        end_time = timetmp.QuadPart;        // accumulate frame times for the average.        frame_time_avg += (end_time-start_time);                //And see if a second has elapsed        if(end_time - sec_e >= second)        {            // Its been a second so put the number of frames rendered into g_fps and clear the frame counter            g_fps = frame_count;            frame_count = 0;                                    //TODO:            if(1) //If fps is being displayed            {                //Display g_fps somewhere               double dAvgFrameTicks = double(frame_time_avg)/g_fps;               double dElapsedMs = (dAvgFrameTicks/second)*1000;               printf("FPS: %d Avg FrameTime: %0.4f ms\r\n", g_fps, dElapsedMs);            }            frame_time_avg = 0;            QueryPerformanceCounter(&timetmp);            sec_e = timetmp.QuadPart;                    }          }

[Edited by - pragma Fury on June 1, 2005 2:55:51 AM]

##### Share on other sites
Thanks pragma, I have been crackin at this all day and still havent got there. I'm give your code a shot now. Unfortunatly I still dont understand how I got such high number for frame_count before.

Edit: Lol I see now... how foolish lol! Thanks again pragma fury

Edit2: Got the code working. Didnt think so at first frame count was 250000 with a frame time of 0.001 which doesnt really add up... But when I add sleep(5) it sit right around 5.001 ms and 200 frame so It seems all is well. Still the count is funky at over 1000fps.

[Edited by - chad_420 on June 1, 2005 3:55:33 AM]

##### Share on other sites
You should consider wrapping your timer up into a class instead of manually calling QPC...That way you can reuse it. Something like this would probably be all you need...

class CHighResTimer{	public:		CHighResTimer()		{			::ZeroMemory(&m_start, sizeof(m_start));			::ZeroMemory(&m_stop, sizeof(m_stop));				LARGE_INTEGER tempFreq;						::QueryPerformanceFrequency(&tempFreq);			//	so we don't have to cast every time we call GetSeconds...			m_freq = static_cast<double>(tempFreq.QuadPart);		}		virtual ~CHighResTimer()		{		}	public:		void StartTime()		{			::QueryPerformanceCounter(&m_start);		}        		double GetSeconds()		{			::QueryPerformanceCounter(&m_stop);			return( (m_stop.QuadPart - m_start.QuadPart) / m_freq);		}		__int64 GetTicks()		{			::QueryPerformanceCounter(&m_stop);			return( m_stop.QuadPart - m_start.QuadPart );					}	private:		LARGE_INTEGER		m_start;		LARGE_INTEGER		m_stop;		double			m_freq;};

hth,
moe.ron