Sign in to follow this  

QueryPerformanceCounter() without polling

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.)

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
Quote:
Original post by andy82Call a function every <ms> milliseconds with the utmost precision that Windows can offer me and without blocking window event handling.

How precise does it have to be? Windows is not a realtime OS, so there are certain limitations on how precise you can get.

Quote:

@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.

I'd do without the precision. Sleep() is not very precise because there is no way it can be. When your app is not actively executing, it has to await its turn. But if you want to be precise, you need to make sure your app is running all the time, which means you have to have 100% CPU usage.
And even then, you aren't sure to get any kind of precision.
Windows decides all on its own which app to run when, and it regularly halts your app in order to run all the other apps for a bit. During that time, you won't be able to handle Windows messages, and you won't be able to query timers because... your app isn't running.
Nothing you can do about that, short of giving your app realtime priority, which is a bad idea for about 200 reasons, and still won't make the problem go away entirely.

That's why I asked how much precision you need. You might be able to get millisecond precision *most* of the time, at least if there aren't too many apps running, and while your app is actively executing, QPC can give you microsecond precision. But only while you're executing. If you're yielding the CPU to let other apps run (or if Windows just decides to interrupt you), you have to wait until Windows feels like resuming your app. And there's nothing you can do about that.

Btw, Sleep(0) might be useful to you. That doesn't actually put your app in a sleep queue, so you won't miss out on anything much, but simply turns the CPU over to Windows, ending your current timeslice.

Share this post


Link to post
Share on other sites
This is either a "real-time" application or it's a typical windows application which doesn't do anything until it gets input.

If it's real time then take 100% of the CPU who cares? You're not actually using 100%, task manager may say so but you're not. Other applications will run perfectly fine unless you're on a PII-350 or something and using XP...

If this is a regular windows application like a web browser then I don't see why you need a game style main loop. But since you've given us basically no information it's difficult to help you.

You've also not told us what sort of accuracies you need in a timer. Nanosecond? Millisecond?

Share this post


Link to post
Share on other sites
I think there are about three possibilities here, and none of them are really an ideal solution:

1. Don't worry about yielding CPU usage and just keep polling away until enough time has passed.
Advantage: Highest accuracy possible.
Disadvantage: Uses 100% CPU.

2. Use sleep(0) to yield to threads of equal or higher priority.
Advantage: Gives programs of equal or higher priority more opportunities to get time slices while you're waiting for enough time to pass, while still polling at a very high rate.
Disadvantage: Still uses 100% CPU (I think) and lower priority tasks still aren't given a chance to run during your sleep(0).

3. Use sleep(1) to sleep for the lowest resolution timeslice.
Advantage: Reduces CPU usage
Disadvantage: Less accurate control of the timing, it may be more difficult or impossible to maintain a steady framerate. It could be that the next frame was supposed to be started much earlier than the amount of time you will sleep for, especially if the game processing does require a significant amount of time. Similiar to waiting for WM_TIMER messages.

Share this post


Link to post
Share on other sites
Another alternative is to use MsgWaitForMultipleObjects instead of Sleep. Then you can have a standard message dispatch loop that is able to timeout when it's time for the next frame.

Share this post


Link to post
Share on other sites

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

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this