Game Loop - Free CPU

Started by
32 comments, last by CrazyCdn 16 years, 11 months ago
I'd recommend MsgWaitForMultipleObjects over Sleep! The benefit is that as soon as there are messages available this function aborts the wait. You can then process these messages and continue waiting until a given time has elapsed. This way your rendering/logic loop is decoupled from your GUI message pump.
void MySleep( float Seconds ){	static HANDLE Timer = CreateWaitableTimer( NULL, FALSE, NULL );	// Determine time to wait.	LARGE_INTEGER WaitTime;	WaitTime.QuadPart = (LONGLONG)(Seconds * -10000000);	if ( WaitTime.QuadPart >= 0 )		return;	// Give up the rest of the frame.	if ( !SetWaitableTimer( Timer, &WaitTime, 0, NULL, NULL, FALSE ) )		return;	for ( ;; )	{		DWORD Result = MsgWaitForMultipleObjects		(			1,			&Timer,			INFINITE,			QS_ALLINPUT		);		if ( Result == (WAIT_OBJECT_0 + 1) )		{			// Execute messages as soon as they arrive.			MSG msg;			while ( GetMessage( &msg, NULL, 0, 0 ) )			{				TranslateMessage( &msg );				DispatchMessage( &msg ); 			}			// Resume waiting until time has elapsed.		}		else			return; // Time has elapsed.	}}

However I don't have tested this code above, but I think you get what I mean ;)

cu,
Chris

EDIT: Fixes!
EDIT: I'D forgot to say that those timer-objects may also give better granularity compared to Sleep!

[Edited by - Christian Weis on May 11, 2007 10:30:43 AM]
Advertisement
Quote:Original post by noooooon
Why a game should allways take 100% CPU if it doesn't need it ?

I didn't say that. I said that it should take 100% CPU if it *does* need it.
I said that we often want our games to run as smooth as possible. Which means the highest framerate possible, which again means 100% CPU usage.
And then I explained why this isn't harmful. You're right though, if you don't need to run "as fast as possible", then you definitely shouldn't use 100% CPU.

Quote:
Quote:
You answered it yourself. They cap the framerate, so if a frame takes less than 1/60th to draw, they wait before drawing the next. Result: Framerate at 60, and on fast CPU's, less than 100% CPU usage.


Yes and how ? How do they wait ? That my question...

Use a timer to record the time at which you started rendering the current frame. Add 1/120th of a second to that, and you know when the next frame should start.
Once you've finished rendering the current frame, you take the current time, and check how far it is from the "next frame" time we computed.
Then you call Sleep(int) with the time difference.

At least, that's how I'd do it given the requirements you set.

Quote:
There are many reasons not to use 100% of CPU :
- The player may use other applications that also use some CPU while he plays (teamspeak, IM, ...)

Yes, and as I said, these other apps *do not get starved out* just because your game uses all the CPU time it can get. Instead, Windows makes sure they all get their fair share. Only the leftovers will be used by your app to reach higher CPU usage than that. If another app uses more of its own allocated CPU time, then there'll simply be less left over for your game, which then won't use 100% CPU. In other words, this particular argument doesn't generally hold. You don't need to worry about whether or not other apps get the CPU time they need. Windows does that for you.

Quote: - The player is on a laptop. CPU consume energy. He could play longer.

Yep. (Although most people only play games on their laptops while they're plugged into AC power. But it's still a valid point, and I agree)

Quote: - The player is a game developper or a tester in game studio. His CPU time could be use to make other things, like cross compilation for example.

See the above. Using "all available CPU time" does not starve out other processes.

Quote:
- your game is used inside another windows application. For example you have a windows application to edit your game levels. You have a viewport that shoes level created inside your game in real time. You dont want this application to use 100% CPU, since its a windows application.

I don't? Don't I want this viewport to update in realtime? And run somewhat smoothly? This particular argument seems to boil down to "you don't want to use 100% CPU because you don't want to use 100% CPU". If I have a viewport in a windows app which is supposed to show the game, then I may want it to run like the game. If I want it to be simpler than the actual game, then I may not need it to run smoothly, and I can use less CPU.

Quote:Now let me reverse the question. Why whould you use 100% CPU if you dont need to ?

Again, that's precisely the opposite of what I actually said. I said that you should use 100% CPU if you *did* need to. If you don't need it, you obviously shouldn't.

Hope that clarifies what I said a bit. I agree, in the case of Pong or other games that don't need much CPU to run smoothly, there's no point in using that much CPU... (You could just enable vsync though, and get a simpler solution. Then the game won't run faster than the monitor's refresh rate, and will automatically yield the CPU if it starts going too fast. This has the nice side bonus that it means the user can force vsync off, if he really wants to see how fast the game can go.)

I'm only saying that *in general*, there's nothing wrong with a game using all available resources, as long as the game can benefit from it. Windows makes sure that other apps won't be starved out, so unless you're writing a game for DOS, you don't really need to worry about that. (And if you're writing for DOS, there won't be other apps anyway, so the point is moot there)
Quote:Original post by DaBono
Quote:Original post by JohnBSmall
Just a little note, since everyone is suggesting Sleep(1) or Sleep(0) to give up the rest of the timeslice for other applications, you might want to use the SwitchToThread() function instead, since it's actually designed to give up one timeslice, rather than being designed to wait a particular period in milliseconds.
Being nitpicky: SwitchToThread() gives up one timeslice, while Sleep(0) gives up the remainder of the current timeslice.


I disagree here - I believe SwitchToThread() operates identically to Sleep(0).
When I compile the core engine it takes 5-10mins at times. During which time I'm playing Counter-Strike (by itself normally uses 100% of the CPU), which runs at over 60fps at all times. I, when dead in CS, talk to people on MSN/Yahoo and/or surf the web (read this site!). The damage of doing all this? 5-10 seconds added to the compile time... Oh no!

The only valid point about not using 100% CPU is for laptops. Our engine lets you specify you're on a laptop and want to use as little CPU as possible. So the engine can set a target frame rate (50fps say for example) and if we're over that it scales back. Otherwise if this is a desktop who cares.

Also, when our window is in focus we go all out, 100%. If we lose focus but are still "visible" (not minimized) we scale back to 30fps using the above technique to be nice. If it's minimized we pause the game. Of course a game using our engine can override this functionality but that's their choice.

Also, we use Sleep(0), anything greater I discovered can cause issues. I'll check out SwitchToThread() again but I thought it actually skipped your next time slice while Sleep(0) gave up the remainder of the current time slice.

The only valid point of not using 100% CPU is for laptops to conserve energy. On any other modern OS this is a non-issue.

Edit: Oh and Warcraft 3 likely handles you tasking out to check CPU usage properly too. Our engine will show like 20% usage if you're tasked out and the game is visible, or 0-5% if it's minimized. So you may not be getting accurate CPU usage numbers if you're just using the Task Manager. If you're relying on the task manager for your Warcraft 3 numbers it's likely invalid.

"Those who would give up essential liberty to purchase a little temporary safety deserve neither liberty nor safety." --Benjamin Franklin

This topic is closed to new replies.

Advertisement