I just noticed today, that when I compile and run a new XNA 4.0 game, one of CPU threads is running at 100% and the framerate drops to 54 FPS.
The weird thing is that so
According to this discussion on XBox Live Indie Games forum , apparently on some processors (and OS-s) XNA takes up 100% CPU time on one core when the default value of Game.IsFixedTimeStep
is used.
A common solution (one that worked for me as well) is to put the following in your Game
constructor:
IsFixedTimeStep = false;
The Game.IsFixedTimeStep property, when true
, ensures that your frame (Update()
, Draw()
, ...) is called at a fixed time interval specified in Game.TargetElapsedTime
. This defaults to 60 calls per second.
When Game.IsFixedTimeStep = false
, the calls to the next frame will happen when the previous one is finished. This is illustrated in the time graph below:
All fixed time calculations (movements, timings, etc.) will need to be modified to accommodate variable time steps. Thankfully, this is very simple.
Suppose you had
Vector3 velocity;
Vector3 position;
for some object, and you are updating the position with
position += velocity;
On default, this would mean that the speed of your object is 60 * velocity.Length()
units per second. You add velocity 60 times each second.
When you translate that sentence into code, you get this simple modification:
position += velocity * 60 * gameTime.ElapsedGameTime.TotalSeconds;
To put it simple: you're scaling the values you add based on how much time has passed.
By making these modifications in places where you perform moving (or timing, etc.), you'll ensure that your game acts as it would back when it was fixed time step.
High CPU usage (100% on one core) is a non-problem for games. In other words, it's expected. The way you're using the CPU when you write a game demands you do this.
Open the code environment and write a simple program
void main(){
while(1) puts( "aaah" ) ;
}
Open the CPU monitor and see that 100% of one core is used.
Now your game is doing this:
void main(){
while(1){
update() ;
draw() ;
while( getTimeElapsedThisFrame() < 1.0/60.0 ) ; // busy wait, until 16ms have passed
}
}
So basically you call update()
and draw()
, and that takes up most of the 16ms you have to compute a frame (which you will take up most of when your game has a lot of stuff in it).
Now because O/S sleep resolution is not exact (if you call sleep( 1ms )
, it may actually sleep for 20ms before your app wakes up again), what happens is games don't ever call the O/S system function Sleep
. The Sleep
function would cause your game to "oversleep" as it were and the game would appear laggy and slow.
Good CPU usage isn't worth having an unresponsive game app. So the standard is to "busy wait" and whittle away the time while hogging the CPU.