Game Loop 100% System Resources

Started by
11 comments, last by ext 18 years, 10 months ago
Hi all:) Can someone please point me to an artikle that could help me optimize my game loop. it runs fine and all but even if the game doesnt do anything it runs at nearly 100% system resource

int WINAPI WinMain(	HINSTANCE hinstance,
				   HINSTANCE hprevinstance,
				   LPSTR lpcmdline,
				   int ncmdshow)
{	


	MSG		   msg;		 // generic message
	Game_Init(hinstance);

	LONGLONG Frequency;
	LONGLONG Offset;
	LONGLONG NextFrame;
	LONGLONG CurCount;
	if(!QueryPerformanceFrequency((LARGE_INTEGER*)&Frequency)){
		ThrowError::Error(Globals::g_main_window_handle,"Could not call QueryPerformanceFrequency");
		return (0);
	}
	
	Offset = Frequency/Globals::g_FRAMERATE;
	QueryPerformanceCounter((LARGE_INTEGER*)&CurCount);
	NextFrame=CurCount+Offset;
	// enter main event loop
	while((TRUE)&(Globals::g_window_closed !=1	))
	{
		// test if there is a message in queue, if so get it
		if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
		{ 
			// test if this is a quit
			if (msg.message == WM_QUIT)
				break;

			// translate any accelerator keys
			TranslateMessage(&msg);

			// send the message to the window proc
			DispatchMessage(&msg);
		}else{ // end if
			QueryPerformanceCounter((LARGE_INTEGER*)&CurCount);
			// main game processing goes here
			if(CurCount>NextFrame){
				int erg = Game_Main();
				NextFrame=CurCount+Offset;
			}
		}
	} // end while
	// closedown game here
	Game_Shutdown();

	// return to Windows like this
	return(1);

} // end WinMain


thx all in advance Rozik
Advertisement
Put Sleep() or some similar function, or use GetMessage() instead of PeekMessage()... [wink]

Ok, seriosly, it works fine. What you did here is infinite loop, and of course it take 100% CPU, as it should...
Bulma
Quote:Original post by Rozik
Hi all:)

Can someone please point me to an artikle that could help me optimize my game loop.

it runs fine and all but even if the game doesnt do anything it runs at nearly 100% system resource


*** Source Snippet Removed ***


thx all in advance

Rozik


I agree with Bulma (although I wonder if Bulma really exists. I always thought it was a manga character): a Sleep(0) somehwere in the loop would definitely help. Be aware that it has a (small) cost, since it gives the control to the next thread.

Regards,
This is common enough: You have a while loop running constantly, eating up all the CPU time it can get. When your game is running you most likly want it too, as it is the most important process (from the users point of view). If you don't wan't it, though, you can put a Sleep(0) in the end of the loop. This will cause your app to surrender any remaining time in its timeslice to other apps. If its doing nothing, then there are lots of time left, and the CPU use will fall.

On a related note, it can be a good idea to check for lost window focus and do something like

if( active )    /* do game stuff */else    Sleep( 100 );


Then you wont hog the CPU when you don't need it.
ok this is what i did now and it reduced the recources used to almost nothing since there isnt anything running but the loop so far

int WINAPI WinMain(	HINSTANCE hinstance,				   HINSTANCE hprevinstance,				   LPSTR lpcmdline,				   int ncmdshow){		MSG		   msg;		 // generic message	Game_Init(hinstance);	LONGLONG Frequency;	LONGLONG Offset;	LONGLONG NextFrame;	LONGLONG CurCount;	if(!QueryPerformanceFrequency((LARGE_INTEGER*)&Frequency)){		ThrowError::Error(Globals::g_main_window_handle,"Could not call QueryPerformanceFrequency");		return (0);	}		Offset = Frequency/Globals::g_FRAMERATE;	QueryPerformanceCounter((LARGE_INTEGER*)&CurCount);	NextFrame=CurCount+Offset;	// enter main event loop	while((TRUE)&(Globals::g_window_closed !=1	))	{		// test if there is a message in queue, if so get it		if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))		{ 			// test if this is a quit			if (msg.message == WM_QUIT)				break;			// translate any accelerator keys			TranslateMessage(&msg);			// send the message to the window proc			DispatchMessage(&msg);		}else{ // end if			QueryPerformanceCounter((LARGE_INTEGER*)&CurCount);			// main game processing goes here			if(CurCount>NextFrame){				int erg = Game_Main();				NextFrame=CurCount+Offset;			}else{                             Sleep(20);                        }		}	} // end while	// closedown game here	Game_Shutdown();	// return to Windows like this	return(1);} // end WinMainthx all in advance


You guys think this is ok or do you have any other suggestions?
A game loop is supposed to take up 100% CPU time. That's what games are - CPU hogs. Optimization of the loop makes the game run faster (higher framerate) but does not reduce CPU usage.

That's my view on it anyways. Your Sleep( 20 ) will make your game's performance suffer greatly.

Cheers!
- fyhuang [ site ]
Yup. Basically, your game loop will use 100% of the resources. If you optimize it, it will use 100% of the resources more efficiently.

For example, since your loop doesn't do anything, we could optimize it like this:
while(1){;}

and then it will use 100% of the system resources . . . but by 'eck it'll run fast!
One common way to reduce cpu consumption is to cap the FPS. Beside this
you can always gear down the rendering process when your application is minimized or such.

In order to cap the FPS to a predetermined value (like 60 fps, see DOOM 3 rendering), you need to measure the average time between rendering calls and adjust with "sleep" commands. There is code on the net for that, but you should create it yourself, it's good practice. But then again, setup some rendering ahead of this.
I think it is important to make a distinction between turnbased games (cardgames for example) and realtime games (FPS, but also turnbased strategy games).

For the first one, you'll only need to rerender the display if something changes. If you have no animations that need running, this means that if the user doesn't do anything, you don't need to do anything either. In such a case, the sleep(.) is very useful, as is the GetMessage instead of PeekMessage, and there is apparently also the function WaitMessage which entirely suspends your program until it receives a message (I have yet to take a look at the last one myself).

For the second category you usually use all the CPU you can. If you nevertheless want to limit the CPU load you will indeed need to limit the framerate. This can be done automatically by enabling VSync (the frame doesn't flip until the monitor is refreshed), or by hand by saying that you only want your game to take action every x ms. If it's not time to take action, Sleep(.) for a short while.
Well, most games always have animations running, so they do need to update the display. If you don't have that, you might be better off using GDI than DirectX/OpenGL

Anyway, why *shouldn't* the game loop use 100% cpu? Thats really the question you need to ask yourself.
Of course it depends on the game, and yes, as was said above, if you're making solitaire, you might not need to update the display 60 times a second.
But in other games, you want to update as fast as possible. Updating as fast as possible means using as many resources as possible.
So, it's up to you to decide. Don't you want the game to run as smoothly as possible? (As was said above, for some games, there might be valid reasonsfor this)

This topic is closed to new replies.

Advertisement