views:

515

answers:

9

The game loop alone is using 50% of CPU Usage, I haven't done any rendering work yet. What i'm doing here?

        while(true)
        {
            if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
            {
                    if(msg.message == WM_QUIT || 
                           msg.message == WM_CLOSE || 
                           msg.message == WM_DESTROY)
                            break;

                    TranslateMessage(&msg);
                    DispatchMessage(&msg);                   
            }
            else
            {
                    //Run game code, break out of loop when the game is over

            }
        }
+8  A: 

Classic busy/wait loop. Your CPU is busily checking (and rechecking ad infinitum) for messages. You need to wait for messages in a blocking way or, more likely, use a timer that periodically wakes up your game thread so it can do its work. The game thread would then go away until the next time it is woken up.

tvanfosson
A timer is not the right approach for a high performance game with a normal render-loop, it needs to render as fast as possible and be greedy for CPU cycles.
John
John is right, BUT you should still use a timer to get the ticks since the last frame, so that you can update your game state accordingly. For example, a door should open at a certain rate regardless of framerate. You can use a timer to calculate the correct amount of movement since the last frame. On Windows, use QueryPerformanceCounter.
Matt Olenik
Yes that's true, the _logic_ should use actual passage of time, but the rendering should run as fast as possible. how you make your game frame-rate independent is a different question.
John
No it doesnt need to render as fast as possible. rendering faster than the screen refresh rate is pointless. It is desirable - always - to be able to block for at least the next screen interval - most graphic frameworks (opengl / directx) only allow display interval synching when running exclusive / full screen applications.Ones next option is to choose a timer that is "good enough" - normally to achieve a frame rate >30fps, but not really faster than 100fps. So a 10 to 33ms timer is normally used.
Chris Becke
Sorry, I've worked in the games industry and that's not true. Most games let you choose whether to enable vsync or not - apart from anything else that's the only way they can use games to do performance tests on new hardware, e.g "Doom3 ran at an impressive 400fps on the new nVidia 999X"
John
and 400fps does what other than prove the size of your ePeen when your monitors refresh rate is 60Hz?
Chris Becke
Most games have a FPS limit option enabled by default; you should provide such an option and put a timer in the main loop: in that way if a user wants to save CPU time (like most users wants, since avoiding unnecessary CPU heating is always a good thing) he'll be satisfied with the default settings; otherwise, if the user wants to show that he enlarged his penis with his super-duper PC, he'll be able to let the game take every resource it can. Bonus points for an option that calibrates the FPS limiter to the refresh frequency of the monitor.
Matteo Italia
+5  A: 

You have created a busy-wait loop. You are probably using 100% of one core, thus 50% of a dual core.

You need to find a way to block on read (in a separate thread), block and fall out of an I/O call as necessary, or do something else useful in the thread. Each strategy has its advantages and disadvantages. Separate threads need synchronized communication methods such as mutexs. Falling out of I/O means nothing else useful happens in this thread when there are no messages. Doing something else in the loop can result in lumpy processing (the "something else" gets processed more on less messages. less on more messages).

kmarsh
You don't need a 2nd thread. This is very basic game programming, tweaking a normal message loop is perfectly standard.
John
+1  A: 

If you're making a very simple game and do all your rendering and calculation in the main loop you need to control how fast the while loop is running, or else the game will run at wildly different speeds on different processors. As a side effect of that you're also making sure the while loop isn't consuming any CPU doing nothing.

A: 

In your else block, try adding this:

sleep(0);

That will cause your thread to yield the CPU, breaking the busy-wait loop. To do your actual game code, use a timer as tvanfosson suggests to wake up another game thread.

Eric Petroelje
A: 

it doesnt look as a standard win32 app main loop ... that is similar to

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
 {
   MSG msg;
   while(GetMessage(&msg, NULL, 0, 0) > 0)
   {
     TranslateMessage(&msg);
     DispatchMessage(&msg);
   }
   return msg.wParam;
 }

as you are inside the while (true) loop maybe even user events (mouse and keyboard) cant get dispatched in the message queue correctly

If your goal is to develop a Game app in win32 i suggest you to look at Directx

luca
Where would you run the game code to update the game objects using GetMessage()?
Dave18
-1 I don't know where to begin... `it doesnt look as a standard win32 app main loop` - it's not supposed to... it's a game. `If your goal is to develop a Game app in win32 i suggest you to look at Directx` - that isn't even the question... *sigh*
George Edison
+1  A: 

I think this behavior is expected. Whenever your game code does nothing, the application furiously checked the message queue using PeekMessage - it's a continuous loop so uses the whole of 1 core.

As you add logic to your else{...} block you will find it remains at 100% use on one core, but the time is spent doing your game logic - only the unused CPU cycles are used on the PeekMessage call, but right now 100% of the cycles are unused.

It is common for a game to max out the CPU when visible, if it's running full-screen. But you should probably consider using GetMessage instead of PeekMessage.

Note, games don't normally work quite the same as normal apps. Normal apps typically do nothing, unless they get a message telling them to do something. Games typically do stuff all the time, because they want to render as many frames/second as possible. Stealing all the CPU is a bit greedy in windowed mode though.

John
well it shouldn't steal all of it if something else is actually running the OS still has its say
jk
games don't normally want to multitask, when running full-screen. They want every bit of performance they can grab.
John
so I'm doing is right?
Dave18
it is still polite not to use all CPU if your doesn't need it. But, it's not automatically a problem. You are using all the CPU, but only because no other apps are trying to use it - you are still checking the message loop, so other apps can still run, slowly.
John
Yeah I guess I don't want to use the game loop when the application is minimized or inactive but the game loop would still use all the available resources and as much CPU It can when its activated.
Dave18
+2  A: 

That's a standard game loop for action games, where you must update objects positions / game world.
If you are making a board game GetMessage would be a better choice.
It really depends on what game you are making.

Nick D
Good point. It depends a _lot_ if you need a high frame-rate in a render-loop or not. If you don't, code it more like a normal Windows app.
John
A: 

You need to give up the CPU when you have no messages to process and no game code to execute. One way to do this is to use MsgWaitForMultipleObjects to wait for a message to show up in your queue or a slice of time to expire.

Something like this

   DWORD g_msNextGameCall;
   DWORD g_msGameTickTime = 1000/75;

   while (true)
      {
      if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE | PM_NOYIELD))
         {
         if (WM_QUIT == msg.message)
            break;

         TranslateMessage(&msg);
         DispatchMessage(&msg);  
         }
      else
         {
         DWORD ms = GetTickCount();
         DWORD msNext = g_msNextGameCall;
         LONG  lWait = 0;
         DWORD dwRet = WAIT_TIMEOUT;

         if (ms < msNext)
            lWait = min((LONG)g_msGameTickTime, (LONG)(msNext - ms));

         if (lWait <= 1)
            {
            g_msNextGameCall = ms + g_msGameTickTime;
            DoGameStuff();
            }
         else
            {
            if (WAIT_TIMEOUT == MsgWaitForMultipleObjects (0, NULL, FALSE, lWait, QS_ALLEVENTS))
               {
               g_msNextGameCall = GetTickCount() + g_msGameTickTime;
               DoGameStuff();
               }
            }
         }
      }
John Knoeller
A: 

Your game is running the fast as possible in one core. This is normal depending of what you did.

I don't know if you want take MORE power (thus reach 100%) or LESS power (and use less of the poor user energy bill...)

If you want to take MORE power, you need to use threading somehow, to use both cores. Since I am not much into threading, I will not even attempt to explain, it is totally not my field.

If you want to use LESS power, there are also two options...

One is "yield" as some game library APIs call it (like Allegro), it consists of making a FPS counter, and giving back control to the cpu every frame for the suffcient time. Example, if your game wants to run at 120 FPS, and you want it to run at 60, you can give to him about the same amount of time that a frame is taking to calculate (about 8,3333... ms).

The other one, is use a event based way to code the game, instead of looping. In that form, you put your code inside a function named "Update" that accepts as argument the amount of time taken since last call (very important this...). This "Update" can be either for the entire app (more classical), or each object having its own (popular after invention of Flash, that use this, as "OnEnterFrame", also Unity use this, and some other engines). And you make a code that throw a interruption and call that Update, usually just a timer that run at a regular time (16.6.... ms for 60FPS, 33.33333... ms for 30FPS).

Obviously, there are a LOT of other ways too, but I will not explain them all, because that is sufficient info for a small book...

I've used the various approaches myself, I like to just use the CPU full blast (without threading), and use more and more system abusive effects as power is made available. But for simpler games, I usually make a loop that "yields", the easiest way usually counting how much time took to calculate everything, subtract that from 16.6 ms, and call a sleep function (that give control to OS for that time) on the result... Like, if a frame took 3 ms to calculate, I call a sleep(16-3). And several engines force me to work with the "event style" (ie: input comes from keyboard, mouse and joystick interruptions, and a timer interrupts and calls "Update(step)" ), I dislike it, but I had to learn...

And a final note: The "step" var as I called (the Update argument), usually is used in the game logic maths, example: "position.x = position.x + speed*step" to make a object move at actual constant speed... (obviously, the operation used, depends on what "step" represent).

speeder