Jump to content

  • Log In with Google      Sign In   
  • Create Account

We need your feedback on a survey! Each completed response supports our community and gives you a chance to win a $25 Amazon gift card!


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


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
15 replies to this topic

#1 savail   Members   -  Reputation: 333

Like
0Likes
Like

Posted 13 July 2013 - 10:16 AM

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!



Sponsor:

#2 Cornstalks   Crossbones+   -  Reputation: 6991

Like
3Likes
Like

Posted 13 July 2013 - 10:28 AM

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


[ 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 ]

#3 savail   Members   -  Reputation: 333

Like
0Likes
Like

Posted 13 July 2013 - 10:59 AM

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.



#4 kauna   Crossbones+   -  Reputation: 2864

Like
1Likes
Like

Posted 13 July 2013 - 12:58 PM

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

 

Cheers!



#5 Khatharr   Crossbones+   -  Reputation: 3084

Like
1Likes
Like

Posted 13 July 2013 - 05:01 PM

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.

#6 Cornstalks   Crossbones+   -  Reputation: 6991

Like
3Likes
Like

Posted 13 July 2013 - 05:50 PM

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.


[ 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 ]

#7 Joshhua5   Members   -  Reputation: 478

Like
1Likes
Like

Posted 14 July 2013 - 12:19 AM

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.



#8 savail   Members   -  Reputation: 333

Like
0Likes
Like

Posted 14 July 2013 - 02:25 AM

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



#9 Tispe   Members   -  Reputation: 1048

Like
2Likes
Like

Posted 14 July 2013 - 02:31 AM

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;
		}
}


#10 Khatharr   Crossbones+   -  Reputation: 3084

Like
0Likes
Like

Posted 14 July 2013 - 04:36 AM

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


Edited by Khatharr, 14 July 2013 - 04:38 AM.

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.

#11 Madhed   Crossbones+   -  Reputation: 3139

Like
1Likes
Like

Posted 14 July 2013 - 08:28 AM


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

 

The original code is actually fine. If there is a message, no frame is rendered. Rendering only occurs when all messages have been processed.



#12 Tispe   Members   -  Reputation: 1048

Like
0Likes
Like

Posted 14 July 2013 - 09:42 AM

 


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

 

The original code is actually fine. If there is a message, no frame is rendered. Rendering only occurs when all messages have been processed.

 

 Yes, I noticed that now. However, I think that code looks tangled.



#13 Shannon Barber   Moderators   -  Reputation: 1390

Like
0Likes
Like

Posted 18 July 2013 - 11:27 PM

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.

 

The utilization will drop when something you call "blocks". PeekMessage is a non-blocking call. Something else is causing the slow down.

When an OS call blocks, it will task swap to other programs while it waits for your blocking call to finish. If nothing needs to run it goes to idle and your utilization will drop.

 

Since your CPU utilization goes *up* when you minimize this strongly suggest to me that you are making a blocking call in your graphics code.

Once you minimize the context or rendering device is malfunctioning, the graphics routines are returning an error (instead of blocking) so your game loop runs flat out.


Edited by Shannon Barber, 18 July 2013 - 11:28 PM.

- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara

#14 SimonForsman   Crossbones+   -  Reputation: 6325

Like
0Likes
Like

Posted 19 July 2013 - 03:27 AM

 

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.

 

The utilization will drop when something you call "blocks". PeekMessage is a non-blocking call. Something else is causing the slow down.

When an OS call blocks, it will task swap to other programs while it waits for your blocking call to finish. If nothing needs to run it goes to idle and your utilization will drop.

 

Since your CPU utilization goes *up* when you minimize this strongly suggest to me that you are making a blocking call in your graphics code.

Once you minimize the context or rendering device is malfunctioning, the graphics routines are returning an error (instead of blocking) so your game loop runs flat out.

 

 

I'm guessing its a v-synced bufferswap that blocks when its not minimized.


I don't suffer from insanity, I'm enjoying every minute of it.
The voices in my head may not be real, but they have some good ideas!

#15 Khatharr   Crossbones+   -  Reputation: 3084

Like
0Likes
Like

Posted 19 July 2013 - 06:03 PM


I'm guessing its a v-synced bufferswap that blocks when its not minimized.

 

 

Probably.


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.

#16 Endurion   Crossbones+   -  Reputation: 3691

Like
0Likes
Like

Posted 19 July 2013 - 11:22 PM

To directly check if your window is minimized you can also use the API directly, IsIconic. The name stems back from the time when minimized windows were shown as icons :)


Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS