Game message loop - using 50% of CPU when window is minimized or inactive

Started by
14 comments, last by Endurion 10 years, 9 months ago

Hey,

This is how my game loop looks like:


MSG msg;
ZeroMemory(&msg, sizeof(msg));

while(msg.message != WM_QUIT)
{
    if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    else
    {
        if( !Render() ) //In Render() function there are all game drawings and calculations 
        {
            MessageBox(NULL, "Failed to render", "Error", MB_OK | MB_ICONEXCLAMATION);
            PostQuitMessage(0);
        }

    }
}

I'm not actually sure what happens in PeekMessage(...) function. When the game window is active and has focus, everything seems to work fine. PeekMessage function seems to distribute CPU to my game in accordance with its needs. More CPU when there's collision, less when nothing happens at all. I experienced however huge growth of CPU when I minimize my window. I probably have dual core processor and thats why it's taking 50% CPU in that time.
When I erase this block of code from my game loop:


if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

it takes 50% of CPU all the time -> that's why I assumed that PeekMessage distributes somehow CPU. Simple infinite loop like this:


while(1)
{}

will also take 50% of CPU.

Why is that happening and how can I prevent this growth of CPU without sleep()? I would be very grateful for help!

Advertisement

PeekMessage just checks if there's a Windows message your app needs to process. It doesn't pause the app or anything. That's what Peek implies. It says "Just check and return true if there's a message waiting and false if there isn't, but be sure to return immediately; don't wait for a message to come if there isn't one."

Programs on the computer run as fast as they can. If your program is a single threaded program and you have a dual core computer, then yes, it will only take 50% when running at full speed (100% of one core).

Hodgman lists some good options here. Another option is to enter a different game loop when your game is minimized that uses WaitMessage() (and then switch back to using PeekMessage when your game is no longer minimized).

[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

Thanks for the answer. The problem is also that my game has multiplayer mode so I can't stall my application becouse client will timeout and disconnect from the server. Even if you say that programs run as fast as they can I still can't understand why my game doesn't use 50% of CPU all the time then? PeekMessage must be doing sth which prevents it from using max of CPU I guess.

Maybe your graphics card isn't able to accept more commands and your CPU is waiting for the GPU to finish?

Cheers!

Since the rendering is probably skipping a lot of its actual work when the window is minimized, you're ending up with a very tight loop that's essentially calling PeekMessage() endlessly. You may want to place a short loop in there somewhere that calls SwitchToThread() until a certain amount of time has elapsed before processing the next frame.

void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

It's possible you have vsync enabled and your program is capped at rendering at ~60fps. Since your update rate is directly dependent on your render rate (just by looking at your loop), you would have less CPU usage because your program would be stalling, waiting for the video card to allow it to draw due to vsync.

When you minimize, it's possible it's no longer rendering, thus vsync no longer limits your program to 60 fps, thus maxing out the CPU.

Just a possibility.

PeekMessage() doesn't save any CPU, though. That's for sure.

[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

It would be because it's a single threaded program and it max's out one core. if you have a dual core that's 50% usage on your CPU or one core with HT. That's the usual reason.

Thanks for answers! I think it's true that it was due to my lack of constant framerate. After adding some framerate the program no longer consumes max of 1 core's processor

You should empty the message queue every frame, not one message per frame.


MSG msg;

	while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
	{
		if(msg.message == WM_QUIT)
			return false;

		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
if(g_Minimized)
Sleep(1);
 } else{
RenderFrame();

}

You can tell if window is minimized


switch(message)
{
case WM_SYSCOMMAND:
		switch (wParam)
		{          
			case SC_MINIMIZE:
				g_Minimized = true;
				return 0;
				break;
			default:
				return DefWindowProc(hWnd, message, wParam, lParam);
				break;
		}
}

You'll want to watch for it to be restored as well when g_Minimized is true. (SC_MAXIMIZE or SC_RESTORE)

void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

This topic is closed to new replies.

Advertisement