Archived

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

An empty GameLoop() takes 100% CPU Usage?

This topic is 5134 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

Whoever read this book, "The Zen of Direct3D Game Programming" by Peter Walsh, or whoever knows a ''lot'' about game programming... ... are my applications supposed to take 100% CPU Usage? This is how the author lays out the structure of a game: int GameInit() { // initializations go here } int GameLoop() { // anything about the game-in-progress goes here } int GameShutdown() { //de-initialization } int WINAPI WinMain( ... ) { ... // window creation and stuff GameInit(); while( TRUE ) { if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) { if ( msg.message == WM_QUIT ) break; TranslateMessage( &msg ); DispatchMessage( &msg ); } else { GameLoop(); } } GameShutdown(); } Now... just like that, with empty GameLoop(), the program, of course, takes 100% CPU Usage. Imagine if I put anything in GameLoop(), not only 100% CPU Usage, but also the computer is very slow in responding to anything I do. I''m just asking about the general structure. Is it supposed to be like that? Is there any function that I can pass control to Windows for a while, like VB''s DoEvents() or something. [edited by - Deuce on November 27, 2003 7:11:59 AM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
100% cpu usage does not necessarily mean slow performance. it just means that there is a process (or more) that''s always in the active state. call WaitMessage in the msg loop to put ur app to in a wait state until more messages come in.

Share this post


Link to post
Share on other sites
Your applications are not necessarily ''supposed'' to take 100% cpu usage, of course

The problem with this often used game loop is that there is always some processing to do: if there are no windows messages, GameLoop() is called. You can imagine that if GameLoop() doesnt actually do anything, it''s called a LOT, while in the case it does input handling, physics, AI and rendering, it may be called a lot less frequent. Like 80 times a second perhaps.

To prevent your application from using 100% processing power, you can limit the number of frames per second by checking whether enough time has passed since the last time GameLoop() was called, and do nothing or ''sleep'' a bit otherwise.

Share this post


Link to post
Share on other sites
You know the task bar at the bottom (WinXP here). The app starts off with a little animation at the task bar, the bar stretches out to reveal the caption of the window. That little animation, with this 100% usage, takes a lot more to load, and even more to animate. I tried to play a movie in the background, it took more than double the time to load to the extent that I got bored and turned off my app.

Now your suggestin with WaitMessage; let''s say I made a Tetris-clone, where would I put that WaitMessage? In GameLoop()? In the PeekMessage() loop? And what does it exactly do? Gives Windows some time to execute other apps?

Share this post


Link to post
Share on other sites
Sponzie,

I tried and made a Pause() function on my own. Just pass a number of milliseconds and it will while() that amount of milliseconds. But again, that while() loop is useless CPU usage. How do delay my app while at the same time give Windows the ability to execute other apps?

Share this post


Link to post
Share on other sites
Sleep(/*time in ms*/);// etc...
and waiting for messages (using WaitMessage) could be a stupid idea, when your app doesnt get a timer msg it could happen that it stops working till the next message arives...

T2k

Share this post


Link to post
Share on other sites
Well I realize that what I normally do is a quick hack that may not be the best way to go, but try putting in a sleep(x) call. I believe that during sleep() the OS can process other messages etc.


edit: this link may be interesting:
http://www.gamedev.net/reference/programming/features/winmode2/page4.asp

[edited by - Sponzie on November 27, 2003 7:45:50 AM]

Share this post


Link to post
Share on other sites
You guys are right. Sleep(0) was the best solution. It still takes 100%, but when I try to do something else (run WMPlayer or whatever) it''s a lot smoother as if I didn''t have a 100%-usage app in the back.


As far as this program I have is concerned (which constantly draws random GDI rectangles on my window with no pause whatsoever), Sleep(0) does the job. Somehow reduces the usage of my app and gives more time to other programs. But I''m thinking later, when I have a game that involves more than just 20 lines of code in GameLoop(), won''t Sleep(0) slow down my game? If it does, it''s unpredictable. You can''t tell how much it will be slowed down. Does anyone know what I mean? I don''t know, I''m still a beginner in game-programming techniques.


By the way, thanks for that last link -- helped!

Share this post


Link to post
Share on other sites
What i actually do is a sleep(x) where x is my frame interval - processing time, but you should be carefull that sleep has different lattencies for 95-98-xp-2k an even for faster/slower cpus (so i check what''s the minimum accurated sleep in a custom sleep function, take the averange all the time blahblahblah)
That allows you to do a nice tetris with 5 or 10% cpu usage on a p3 1gz (yes... time figures varies... gdi vs dx, etc etc)
Is ok to use 100% cpu on a game but my prefeered way is to release cpu if possible for the other applications that may be running (aka video playback comming from a different thread or process inside your game, an external mp3 player like winamp, etc)

-Mat

Share this post


Link to post
Share on other sites
This has to do with the way PeekMessage operates. What''s happening is that you are calling PeekMessage repeatedly during one time slice. Remember that a each active process is allocated a certain amount of time to execute. When that time is up, execution switches to the next active process.

Internally, if no messages are present in the message queue, PeekMessage Yields the to the next process, then when control comes back it returns NULL. Yield() is different than Sleep(), and has an impact on other processes that prevents them from getting their window messages. GetMessage actually puts the process to Sleep, which is why a normal Windows message loop doesn''t suffer the same problems you have with the typical game loop.

So by not calling Sleep(0), you are creating a situation where other applications are not getting their messages, thereby becoming sluggish. Sleep(0) alleviates that situation. Conversely, when you have a lot of processing going on during a time slice and PeekMessage is called less often, you don''t run into the problem. So with a standard game loop, you''re better off doing a lot of processing rather than very little.

To understand more, read this article.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
in addition to the above suggestions of using GetMessage and Sleep, on Windows, calling SetPriorityClass to flip the app between the idle priority class and normal or high priority classes will help the app let the OS know that it doesn''t or does need the cpu as much as other apps. there''s also SetThreadPriority for a per thread case.

i personally use a combination of all of these methods. if the app puts itself into an inactive state, then GetMessage is called instead of PeekMessage, and the window is redrawn via WM_PAINT processing rather than via the gaming loop. Sleep is used to get close to a desired frame rate, after adjusting for latency considerations via the functions available in the multi-media kit, and finally, thread''s adjust their priority to suit their needs and overall game play impact.

Share this post


Link to post
Share on other sites
Great. I liked that link of MSDN, Aldacron. But something didn''t make sense. Here''s what MSDN said about WaitMessage in that link:

"Most applications that do background processing implement a PeekMessage loop in the following manner (this is pseudocode):

if (PeekMessage(...) != NULL)
// Translate & dispatch the message
else if (there is background processing to perform)
// Perform background processing
else
// No background processing, no messages - go to sleep
WaitMessage();

Used in this manner, the application puts itself to sleep using WaitMessage if there is no background processing to perform and there are no messages to process. It is important that applications do not sit and spin in a PeekMessage loop when in an idle state. An application spinning in a PeekMessage loop will not appear to Windows as idle. This will prevent Windows from performing idle processing like flushing disk cache buffers and performing power management optimization on battery-powered systems."


After reading the pseudocode, the paragraph is misleading. How is it supposed to sit down idle? It says don''t spin around a PeekMessage() loop, instead WaitMessage() "until" not idle. That "until", where would someone check its occurance? If I had to answer that question, I''d say PeekMessage() to see if something came up; but that again makes it "NOT" idle. It''s a paradox -- It says don''t do that, but do it.

By the way, this question has nothing to do with my GameLoop() question anymore -- that question has been answered with Sleep(). I''m now asking about WaitMessage()

Share this post


Link to post
Share on other sites
Again, it has to do with the fact that PeekMessage yields and WaitMessage sleeps. Using PeekMessage + WaitMessage is the same as using GetMessage, except now you have the option of doing any background processing you need to do whne there are no messages to process. Using GetMessage, you don't have that option.

EDIT:

To clarify, go back and read the bit about what happens to the message queue when yielding vs. sleeping.

[edited by - aldacron on November 27, 2003 10:07:19 AM]

Share this post


Link to post
Share on other sites
quote:
Original post by Deuce
Great. I liked that link of MSDN, Aldacron. But something didn''t make sense. Here''s what MSDN said about WaitMessage in that link:
After reading the pseudocode, the paragraph is misleading. How is it supposed to sit down idle? It says don''t spin around a PeekMessage() loop, instead WaitMessage() "until" not idle. That "until", where would someone check its occurance? If I had to answer that question, I''d say PeekMessage() to see if something came up; but that again makes it "NOT" idle. It''s a paradox -- It says don''t do that, but do it.
(). I''m now asking about WaitMessage()


If you call WaitMessage you don''t have to check with PeekMessage since WaitMessage will return when there''s a message in the queue.
Take the MSDN article with a graint of salt, not only is old but obsolete, as it refeers to 16 bit windows nonpreemptive approach (for example, you don''t yield anymore explicitly... look at the api itself).
An application cannot block other applications from receiving their windows messages (ok they can, but is not simple and not with the common API''s, nothing to do with peekmsg and so...).
Decisions about WaitMessage or sleep really depends on your kind of application/game nature, if you''re drawing 60 frames per second is hard to think on getmessage as a good solution for it since it will ''sit'' your thread until windows sends some message.
If your game is driven by keyboard input or mouse clicks then it may make some sence to do it with getmessage but still the architecture tends to be event-driven (or as i like to describe: spaghetti-type)

Share this post


Link to post
Share on other sites