C # / XNA Giant memory leak

This is my first post here. I am making a game in Visual Studio 2010 using XNA and I hit a giant memory leak. My game starts with a 17k bar, and then ten minutes later to 65k. I launched some memory profilers, and they all say that new instances of the String object are created, but they are not live. The number of live instances of String has not changed at all. It also instantiates Char [] (which I would expect from it), Object [], and StringBuilder. My game is fairly new, but there is too much code to publish. I do not know how to get rid of cases that are not alive, please help!

+3
source share
2 answers

You have not posted enough information to provide you with a more than reasonable guess. Here is my reasonable guess:

If you do such things in the Draw method:

spriteBatch.DrawString(font, "Score: " + score, location, Color.Black); spriteBatch.DrawString(font, "Something else: " + foo, overHere, Color.Black); spriteBatch.DrawString(font, "And also: " + bar, overThere, Color.Black); 

Then, each of these calls will create new string and StringBuilder behind your back each time they are launched. Since they are in your Draw method, each of them probably works 60 times per second. These are many temporary objects that stand out!

To verify that this is the case, use the CLR Profiler. Looks like you already did it.

As long as this is not a "leak" - the garbage collector will eventually clear them - this distribution pattern is not desirable in the game. See this blog post for two ways to deal with garbage collection in the game. Method 1 is usually simpler and provides better results - which is why I discuss it here.

At this point, it is worth mentioning that the GC on the PC is fast enough so that distributions like this do not matter . GC will clean up tiny objects (like your timelines) with very little overhead.

On the Xbox 360, on the other hand, even producing small amounts of garbage like this can cause serious performance problems. (I'm not sure about WP7, but I would personally treat it like an Xbox - with caution!)

How to fix it?

The answer is simple: DrawString will accept an instance of StringBuilder instead of string . Create one instance of StringBuilder , and then reuse it every time you need to assemble a custom string.

Note that converting a number or other object to a string, implicitly or using the ToString() method, will also result in a distribution. Thus, you may need to write your own code to add to StringBuilder without causing selection.

Here is one that I use in the form of an extension method to add integers to a string without highlighting:

 public static class StringBuilderExtensions { // 11 characters will fit -4294967296 static char[] numberBuffer = new char[11]; /// <summary>Append an integer without generating any garbage.</summary> public static StringBuilder AppendNumber(this StringBuilder sb, Int32 number) { bool negative = (number < 0); if(negative) number = -number; int i = numberBuffer.Length; do { numberBuffer[--i] = (char)('0' + (number % 10)); number /= 10; } while(number > 0); if(negative) numberBuffer[--i] = '-'; sb.Append(numberBuffer, i, numberBuffer.Length - i); return sb; } } 
+5
source

There are no memory leaks in C # (or they are very difficult to get). What you are experiencing is normal. The garbage collector does not "feel" as if it needs to collect memory, so no. Whenever memory runs out, garbage collection occurs. If you are absolutely sure that you do not keep unnecessary references to your string s, then everything is fine.

If you want to force use the GC GC.Collect() loop.

+2
source

All Articles