The other day a friend of mine was telling me about his XNA game. He’s a huge XNA fan. In fact, he’s almost sworn of C++ entirely. (His loss.) He was telling me about how he fixed this hiccup he had in his frame rate. He simply calls GC.Collect() every frame.

“Whoa,” I thought to myself. The red flag went up. Violate everything that the garbage collector does behind the scenes? I knew it sounded like a crutch, but I didn’t know why. I started a massive volume of research.

One of the first sites I came across was this one, Rico Mariani’s Performance Tidbits. Performance Tidbits? Sounded good. However, the site mostly talks about why each part of the GC.Collect call is bad business. It doesn’t really cover why we shouldn’t call GC.Collect every frame to reduce the garbage being collected each time.

That was quickly followed by this site, Pandemonium, which was another that simply asked us to reduce the amount of garbage being collected. It constantly referenced this book. (Effective C#: 50 Specific Ways to Improve Your C#) It was kind of interesting to see all of the various ways that garbage gets created without you knowing it. For example:

1
2
3
4
string tempString = "Hello";
tempString += " ";
tempString += "World";
tempString += "!";

Here you have created four strings; “Hello”, “Hello “, “Hello World”, and “Hello World!”. Now, that’s four strings that you will be collecting later, when you might have thought you’d only create one. Interesting tips, but not the answer to my question.

Continuing my search, I came across, How to Write High Performance C#, which was more of the same. The cool part of this article is that it covered some of the tools to use and some methods of benchmarking. Also, another tip for helping the garbage collector out by making sure that objects which will be destroyed are done so as quickly as possible. Objects go from generation to generation and get more expensive to collect if they live longer. There was another warning about calling GC.Collect. This seems fairly common, but no one thus far has really said why you can’t call it every frame to reduce the overhead of calling it.

A page or two later, I saw a site called Guidance Share. One small tip I saw here was an arguement for not calling GC.Collect ever.

The garbage collector is designed to be self-tuning and it adjusts its operation to meet the needs of your application based on memory pressure. Programmatically forcing collection can hinder tuning and operation of the garbage collector.

That sounds great and all, but it can’t possibly be the only idea behind it. Otherwise, it could be argued that by calling the collect every frame we’ve tuned the garbage collector to our needs and .Net can either follow our lead or get out of the way. We’ll do full collections every frame. (This still sounds bad to me.)

Then I stumbled upon this article from the .Net Compact Framework team, some of the guys behind XNA. It had a volume of good information, some if which seemed obvious or that I’d seen before, but it did have one little nugget about collection.

One thought that occurs to people is: “Why not call GC.Collect() every frame so it’s deterministic!”. The wasted overhead you get for “over collecting” typically doesn’t make sense.

At 60fps each frame takes about 16.67ms (that’s 1000ms/60frames). Isolated benchmarks show that a GC of 100,000 live objects takes about 14ms (though that’s a relatively large number of objects compared to Rocket Commander by Benjamin Nitschke which has just under 50,000 live objects at peak). Would you really want to sacrifice 80% of your game forcing GCs (~14ms/17ms)? Don’t think so.

So from the mouths of the XNA guys, the overhead is simply too great. I doubt his game is generating even 50,000 live objects (although with boxing, pass-by-value, and concatenation creating objects, who knows) so his overhead would not be that high. However, the basic principle remains. Why spend so much time EVERY frame collecting your garbage? In fact, why generate so much garbage every frame?

But please, don’t take my word for it. Any site on the internet (including mine!) is subject to criticism. If you have this problem, maybe you need to try generating less garbage, re-using objects, and reducing the amount of boxing / unboxing. Maybe you’re fine with calling GC.Collect every frame.

  • Share/Bookmark