How to Measure Frametime in XNA


If you’re making games, it’s pretty much a requirement that you know your frames-per-second at any given moment during development. Even more valuable than your FPS is knowing how much time it takes you to draw a frame. This article by Robert Dunlop does a wonderful job of explaining why you should prefer frametime over FPS as a performance metric.

So, now that you’re convinced that you want to know your frametime, let me show you how to calculate it and put it up on the screen.

When measuring time, it’s helpful to have a stopwatch handy. Luckily, .NET has just such a utility available called, conveniently, Stopwatch. Using this class is as simple as instantiating it and starting it like so.

protected override void Initialize()
{
   // TODO: Add your initialization logic here
   stopWatch = new System.Diagnostics.Stopwatch();
   stopWatch.Start();

   base.Initialize();
}

With our timing device ready, we just have to find the right place to do our timing. For an XNA application, the Draw() function seems likes the perfect spot along with a bit of code to output the results to the screen.

protected override void Draw(GameTime gameTime)
{
   TimeSpan drawTime = stopWatch.Elapsed;
   stopWatch.Reset();
   stopWatch.Start();

   GraphicsDevice.Clear(Color.CornflowerBlue);

   // TODO: Add your drawing code here
   spriteBatch.Begin();
   spriteBatch.DrawString(stopWatchFont, "ms: " + drawTime.TotalMilliseconds, Vector2.UnitX * 600.0f + Vector2.UnitY * 20.0f, Color.DarkMagenta);
   spriteBatch.End();

   base.Draw(gameTime);
}

At this point, we should be ready to measure our frametime. However, if you run the code as-is, you run into a little problem. You'll find that, even without drawing anything, your frametime will stick at 16 milliseconds. Because XNA defaults to running synched to the vertical retrace of your monitor (also known as vsync), the Draw() function will not be called at a rate that is faster than your monitor's refresh rate. This is great for preventing screen sheering, but makes it hard to measure the amount of time it takes to draw a frame of your game. Luckily, you can disable vsync with a couple of flags in the constructor of your Game class.

public Game1()
{
   graphics = new GraphicsDeviceManager(this);
   Content.RootDirectory = "Content";

   this.IsFixedTimeStep = false;
   graphics.SynchronizeWithVerticalRetrace = false;
}

There! Now you should be getting a reasonably accurate reading of your frametime in milliseconds. Go forth, make games, and may your frametime never stray above 16 milliseconds.

Share this Article:
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Yahoo! Buzz
  • Twitter
  • Google Bookmarks
  • Print