Fixing Garbage Collection issues when developing for XNA and XBOX 360

The easiest way for a small indie company or hobbyist developer to develop for the XBox 360 is using the XNA tools from Microsoft. Microsoft have spent a substantial amount and time on the XNA product set.

The XNA framework is a low barrier way to games development. XNA development makes use of a XBox specific version of the .NET compact framework. However, this framework does of course have its issues. The libraries aren’t as complete as the non-compact version, etc.

The way memory works in the .NET framework and the Garbage Collector, the generations of collection, heap allocations and similar are well discussed in a number of locations (not least of which is the MSDN library) and so I shall not discuss those specifics here.

This post is about one specific issue – stalls due to garbage collection events firing off at an inconvenient time. At this point I would strongly recommend reading two excellent articles: Steve from StevePro Studios suggested that I investigate garbage collection when I was developing a game called “flap”. A simple sprite game that would stall every few seconds. Go check out Steve’s original articles . There are other articles out there that explain a fair bit of the inner workings of managed code. Boxing and unboxing is especially interesting.

Once you have read Steve’s original article you will understand that there are generally three values in the remote performance monitor to look out for.

  • Managed String Objects Allocated
  • Managed Objects Allocated
  • Boxed Value Types

So you understand how to use the remote performance monitor, you can see that a static scene is allocating 2000 strings each time it updates – what do you do now?

At this point go back to first principles. When you don’t know where the problem lies profile it. Sometimes, and I will admit this, you can guess where the problem is “oh yeah its because I have spriteBatch.DrawString(font,string.Format(“You have killed {0} baddies”,score, … ) in my main draw code”. But I’m becoming an old hand at this – I get surprised way more than I predict. My recommendation is nothing more than dust down the old CLRProfiler.

The current CLRProfiler is available here:

The technique is very simple.

  1. [To find a scene to target for our investigation we do some precursor steps]
  2. Create a Xbox version of the game.
  3. Deploy to the XBox and use the remote performance manager to run the game.
  4. Find a scene that is static enough (e.g. a simple spinning of the camera around the Y axis) that you shouldn’t expect any allocations.
  5. Find, using the performance manager that there are in fact allocations and GC cycles occuring.
  6. You have now a specific and very targeted problem to solve. This is the key, bite off small chunks and solve them one at a time.
  7. Create a debug windows version of your game.
  8. Start the CLRProfiler.
  9. Set the working directory correctly.
  10. Set the “Profile Allocations” to be true.
  11. Set the “Profiling Active” to false.
  12. At this point you are ready to go.
  13. Launch the application.
  14. Now, navigate to the same point as “4” above.
  15. Click on the “Profiling active” checkbox.
  16. Collect some data for a few tens of seconds.
  17. Uncheck the “Profiling Active” checkbox.
  18. At this point use the call graph to see what objects are being allocated and where.