Archived

This topic is now archived and is closed to further replies.

Programmer16

Using 80+ of my CPU

Recommended Posts

I just had a little question. How come when I use PeekMessage() in my programs, my app''s CPU Usage shoots upto above 80 (Under Windows Task Manager for WinXP)? If I use GetMessage() it doesn''t even go above 0. I know that PeekMessage() is constantly checking the message queue instead of waiting for a message, but should it be using 80+? Thanks /* I use DirectX 8.1 and C++ (Microsoft Visual C++ 6.0 Professional edition) */

Share this post


Link to post
Share on other sites
When you use GetMessage your program is effectivly paused until a message arives. The function does not return, so your program is not checking for messages. Because the program is not doing anything at all. It is given no cpu time and is 0.

When you use peekmessage your program is continuosly checking for messages itself, its always active and so uses as much cpu time as the system decided is free.
Its 80 because the cpu time is devided by the number of apps that need it. Run two instances of your test program and they should both get around 40.

HTH

[edited by - empirical on March 20, 2004 7:38:42 AM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
If you want to use PeekMessage (for whatever) in a loop, you can call Sleep(0); at the end of the loop to conceed spare cpu time to other processes that might need it (according to the docs the rest of the processes time slice for that round of cpu time is given back to the system if Sleep is called with a parameter of 0)

Share this post


Link to post
Share on other sites
make sure and only call sleep when you DONT have a message to handle ... you do NOT want to call sleep when you did find and handle a message ... cause you want to keep going through messages for your whole time slice

Share this post


Link to post
Share on other sites
Isn''t it bad to call Sleep()? I was told that it might sleep longer than the supplied time. Thanks.

/*
I use DirectX 8.1 and C++ (Microsoft Visual C++ 6.0 Professional edition)
*/

Share this post


Link to post
Share on other sites
It might, but the OS already can take control away from your program when ever it wants, for however long it wants.

The 'guarantee' is that Sleep(5) will sleep at least 5 milliseconds (no less). You can use SleepEx if you want to be awoken earlier for unusual conditions.

If you have no work to do, and there are no messages, you should sleep. Ideally you'd sleep until a message arrives or you have work to do again, but a Sleep(1) or Sleep(10) will get you started.

[edited by - Magmai Kai Holmlor on March 21, 2004 1:00:56 AM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
For better or worse I tend to do something along the lines of:
while(1) {
while(PeekMessage(&msg,...,PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// ... do loop stuff here (processing, rendering etc.)
Sleep(0);
}

Share this post


Link to post
Share on other sites
This is how I learned to do it:
while(mMsg.message != WM_QUIT)
{
if(PeekMessage(&mMsg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&mMsg);
DispatchMessage(&mMsg);
}
else
{
GameLoop();
}
}

/*
I use DirectX 8.1 and C++ (Microsoft Visual C++ 6.0 Professional edition)
*/

Share this post


Link to post
Share on other sites
Programmer16, your example is fine, and works fine, but doesn't give up unneeded CPU back to other applications as soon as it could ... so it is less well behaved than it could be. Windows will of course TAKE the cpu away from you when your time slice is over, but you KNOW you do not need it when you have no messages in them message queue, so why not give it back (like th AP above your post does) ...

that's really what this question is all about ... if any program uses your system (and mine for my first 2 years of windows programming - cause I hadn't been sure sleep wouldn't hurt me) - then the CPU meter on that machine will always stay near 100% ... when it shouldn't ... just having a window open that's not doing any work, shouldn't look like it's busy all the time.

Hence the Sleep() call.

heres the codumentation quote strait from microsoft:

quote:

Parameters

dwMilliseconds

(in) Minimum time interval for which execution is to be suspended, in milliseconds.

A value of zero causes the thread to relinquish the remainder of its time slice to any other thread of equal priority that is ready to run. If there are no other threads of equal priority ready to run, the function returns immediately, and the thread continues execution.

A value of INFINITE indicates that the suspension should not time out.



so you see, Sleep(0) is you way of telling the OS - I'm not really busy right now, so let someone else run, but get back to me as soon as you can ...

And the REAL REASON this is a GOOD THING(tm) is because windows IS going to take the CPU away from you anyway, to give other processes a timeslice to run, so wouldn't you rather they start their time slice the MOMENT YOU DON'T NEED THE CPU ... instead of some random time you are busy churning away ... if you give up the cpu, the other processes go ... if that starts when you want it to, it will get back sooner, than if you had spun through your loop an extra 5 ms, THEN windows acted ... cause in that cause, you'd get the CPU back 5 ms later (all other things being equal) - AND the user would wonder why your program is written to always be churning ... when they don't see anything happening ...


[edited by - Xai on March 21, 2004 1:03:55 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by Xai
...but you KNOW you do not need it when you have no messages in the message queue...
Take a look at his loop structure. GameLoop() gets called when there are no messages in the message queue. Which, I presume, would not be an ideal time to sleep.

The truth is that we have terrible notions of the main game loop, and particularly of handling the Windows message pump. Introductory texts set up a basic loop/pump based on the notion that the game updates single step (as opposed to interpolating multiple step), resulting in these debates.

Share this post


Link to post
Share on other sites
ah, well I don''t have a game loop that does anything not using the message queue ... i just put a message in the queue whenever I need to continue the operation after letting other messages get handled ...

for instance my 2d graphics library does a DrawScreen by posting a DrawScreenObject message (a custom message of my own) with the object to draw next ... inside the handler, it invokes draw, and posts another message to draw the next item (if there is one) ... so it stays busy USING the message loop ... until the process is complete ...

and of course, a game in which the time is passing even when the user is doing nothing has some sort of timer type message generation ..

truth be told ... my most advanced windows program does hog cpu, because I needed more acurate timers than you can get with the built in system ... but what I would do now I think is something like have a bool ... then my code would be something like:

while(1)
{
while(PeekMessage(&msg,...,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if(!GenerateTimerMessages()) // return false when no timers are triggered
Sleep(0);
}

now ... i must admit I have never written really intense game ... like an FPS or anything .. the most active game I''ve written in windows is an 8 line video slot machine ... and so maybe these techniques are not efficient enough for many uses ... I don''t know.

Share this post


Link to post
Share on other sites
and actually the above post is wrong anyway .. because I don''t let my timers not get checked if the queue never goes empty ... I actually have something in the inner while that counts to like 10 or so, and force checks the timers for every 10 messages that go by ... that way it can''t be completely starved ... just gets bogged down.

and as some extra sophistication, some of my messages are "update" or "trigger" type messages, such as "DrawFame" so these things don''t every post multiple entries into a backed up queue ... they are set to NotPostDups, so I have a flag I set when I post one, and clear when I handle it ... to keep things sane ... but other messages, MUST be posted no matter what, if their effect is cummunulative ...

Share this post


Link to post
Share on other sites