QueryPerformanceCounter() without polling

Started by
12 comments, last by Anon Mike 16 years, 11 months ago
Hi, I've found out that WM_TIMER is not precise enough for my needs so I thought I'd give QueryPerformanceCounter() a try. I don't see, however, how I could integrate QueryPerformanceCounter() in my main loop without constantly polling the time. If I would use something like this, the CPU usage would be 100%:

while (mssg.message!=WM_QUIT) { 

    // is there a message to process? 

    if (PeekMessage( &mssg, NULL, 0, 0, PM_REMOVE)) { 

        // dispatch the message 

        TranslateMessage(&mssg); 
        DispatchMessage(&mssg); 

    } else { 

        // do we need to move? 

        if (move_flag) { 

            // yes, move and clear flag 

            MoveObjects(); 
            move_flag=FALSE; 

        } 

        // use the appropriate method to get time 

        if (perf_flag) 

            QueryPerformanceCounter((LARGE_INTEGER *) &cur_time); 

        else 

            cur_time=timeGetTime(); 

        // is it time to render the frame? 

        if (cur_time>next_time) { 

            // yes, render the frame 

            RenderFrame(); 

            // set time for next frame 

            next_time += time_count; 

            // If we get more than a frame ahead, allow us to drop one 
            // Otherwise, we will never catch up if we let the error 
            // accumulate, and message handling will suffer 

            if (next_time < cur_time) 
                next_time = cur_time + time_count; 

            // flag that we need to move objects again 

            move_flag=TRUE; 

        } 

    } 

} 

So I was wondering whether or not there is another way of using QueryPerformanceCounter() without a polling loop? The only solution that currently comes to mind is to use a separate thread which does the timer stuff, then sleeps for a while, and signals the main thread after the time has elapsed. But I'd much prefer a solution without a separate thread for simpleness' sake... Thanks for any thoughts on this issue. Andy
Advertisement
You are gonna have to poll that function. How else would you get current timestamp ?
Well, in a separate thread I could do a QueryPerformanceCounter(), then sleep for the while until the next frame has to be drawn, then signal my main thread. That would be a solution without a hard-core polling loop but it requires the overhead of another thread.
Quote:Original post by andy82
If I would use something like this, the CPU usage would be 100%:

Which would not be a bad thing, per se. Many games use 100% of your CPU, since their designed to be the only important application running. I actually want my games to run at the highest frame rate achievable, not caring if my CPU would be actually used to the max.

Note, this may be a different in some web-based game, but I don't think you're building some ActiveX-based app, are you?
Quote:Original post by DaBono
Quote:Original post by andy82
If I would use something like this, the CPU usage would be 100%:

Which would not be a bad thing, per se. Many games use 100% of your CPU, since their designed to be the only important application running. I actually want my games to run at the highest frame rate achievable, not caring if my CPU would be actually used to the max.

True, but it misses one fairly important point. It doesn't matter whether or not you're the only application running. If another app needs CPU time as well, the two apps will automatically share it. Windows will take care of that. You can only get 100% CPU usage if no other app needs the CPU. Which means you don't need to "feel sorry" for the other applications. They're fully capable of taking the CPU when they need it.

However, back to topic, I fail to understand:
1: What is the problem with just querying QPC from the active thread when you need the time?
2: How does any of this affect whether or not the app runs at 100% CPU?

Why don't you just call QPC once per frame, if you need the time once per frame?
Well, the thing is a little more complicated than I described it. I want my game to run at a user-definable speed. So it would be possible that the user sets some nonsense FPS values, e.g. the game shall run at 0.1 frames per second. Configuring my game to 0.1 FPS would need my game to draw a new frame every 10 seconds. Now, consider this case. If I do something like this now:

BeginLoop
PeekMessage()
DispatchMessage()
QueryPerformanceCounter(...)
Sleep(<rest of the 10 seconds>)
DrawNextFrame()
WendLoop

With this code the CPU usage would not be 100% because I'm sleeping until the next frame needs to be drawn but the big problem now is that window events are not handled for 10 seconds because my game is put to sleep. Thus, the game is BLOCKED for almost 10 seconds which is very bad.

What I need would be the following: Put the game to sleep for some time, but be still able to handle window events.

Of course, the code scheme above would work just fine with a 50fps game without necessarily taking 100% of the CPU but I want the game to run at a variable speed and values like 0.1fps should also be possible without blocking the window.

Any ideas?
May I ask why you want the frame-rate to be user-defined? It seems a little strange. If you're looking to be able to adjust the game's relative time (say, like bullet-time in Max Payne) then there are much better ways to handle it.

Understand that Sleep guarantees only that it will put the thread to sleep for at least the time you pass in. When using this method, the incurred 'oversleeping' tends to accumulate so that your frame-rate is variably, but notably, below what you might hope for. If you need a more accurate method, then you'll have to resort back to QueryPerformanceCounter (or maybe GetTickCount) at the cost of some CPU time.

Admiral
Ring3 Circus - Diary of a programmer, journal of a hacker.
Quote:Original post by andy82
With this code the CPU usage would not be 100% because I'm sleeping until the next frame needs to be drawn but the big problem now is that window events are not handled for 10 seconds because my game is put to sleep. Thus, the game is BLOCKED for almost 10 seconds which is very bad.

First, why? Just why? Why would *anyone* make an explicit setting allowing the user to run his game at 0.1fps? What is that supposed to gain anyone?
Second, you could just detach the logic for listening for Windows messages from the render loop. Render once per 10 seconds if that's what you really want, but let your main loop tick away listening for Windows messages, and if necessary, updating game state.
Or more specifically, something like this:

for (;;){  HandleWindowsMessages();  if (IsNotYetTimeToRender()){    Sleep(100); // 100 millisecond sleep intervals should allow you to keep up with Windows messages    continue;  }  RenderFrame();}


Quote:
What I need would be the following: Put the game to sleep for some time, but be still able to handle window events.

But that has nothing to do with querying QPC.
I still don't see the connection to whether or not you should be polling QPC (which, by the way is the only way to get accurate time. Having a timer put a message into a message queue, *which you then read some unspecified time later, when you feel like it* is *not* a viable way to get accurate timing information. To get the accurate time, you need to ask for the time, when you need it, because timestamps have this tendency to get outdated if they just lie around in a queue waiting for someone to read them.)
Well, I tried to illustrate the issue a little. Actually, I'm not doing this for a game but for an application on the Windows desktop. Thus, it is very important that my app takes only as much CPU time as it really needs. So, in other words, what I really want is precisely this: Call a function every <ms> milliseconds with the utmost precision that Windows can offer me and without blocking window event handling. The <ms> are user configurable. <ms> could be both extremes: 20ms for 50fps but also 10000ms for 0.1fps.

I know there's a function called timeSetEvent() which does exactly what I want, but as far as I understand that function is not going to be much more precise than WM_TIMER, or am I wrong here? I didn't try it out yet. I only found out that WM_TIMER is not very precise.

@Spoonbender:
Your suggestion to Sleep(100) to keep up with Windows messages is not precise enough for my case. But maybe a Sleep(1) would give me the required precision. I would have to try that out.

@Admiral:
This is somewhat off-topic, but if Sleep() is not very precise how would you put the application to sleep without using the Sleep() function? Of course, I don't want to poll QPC() until the time has elapsed because that eats 100% percent of the CPU.
Quote:Original post by andy82
I know there's a function called timeSetEvent() which does exactly what I want, but as far as I understand that function is not going to be much more precise than WM_TIMER, or am I wrong here? I didn't try it out yet. I only found out that WM_TIMER is not very precise.

timeSetEvent() probably is more precise than WM_TIMER - the multimedia timing functions generally are. You'll probably need to increase their accuracy with timeBeginPeriod() and timeEndPeriod() (before and after your main loop).

Quote:@Spoonbender:
Your suggestion to Sleep(100) to keep up with Windows messages is not precise enough for my case. But maybe a Sleep(1) would give me the required precision. I would have to try that out.

@Admiral:
This is somewhat off-topic, but if Sleep() is not very precise how would you put the application to sleep without using the Sleep() function? Of course, I don't want to poll QPC() until the time has elapsed because that eats 100% percent of the CPU.

You could try SwitchToThread() which is possibly more likely to only yield a single timeslice (I have no evidence for this though, so you'll have to test it). I doubt that would be much more precise though - it depends on the Windows scheduler using small time-slices, which is not a good thing to rely on.

They (Sleep and SwitchToThread) might work better if you bump up the priority of your thread.

John B
The best thing about the internet is the way people with no experience or qualifications can pretend to be completely superior to other people who have no experience or qualifications.

This topic is closed to new replies.

Advertisement