C#/XNA Giant Memory Leak

两盒软妹~` 提交于 2019-12-12 08:16:21

问题


this is my first post here. I'm making a game in Visual Studio 2010 using XNA, and i've hit a giant memory leak. My game starts out using 17k ram and then after ten minutes it's upto 65k. I ran some memory profilers, and they all say that new instances of the String object are being created, but they aren't live. The amount of live instances of String hasn't changed at all. It's also creating instances of Char[] (which i'd expect from it), Object[], and StringBuilder. My game is pretty new but there's too much code to post here. I have no idea how to get rid of instances that aren't live, please help!


回答1:


You haven't posted enough information to provide you with more than an educated guess. Here is my educated guess:

If you are doing things like this in your 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 those calls will be creating new string and StringBuilder objects behind your back each time they run. Because they are in your Draw method, each is probably running 60 times per second. That is a lot of temporary objects being allocated!

To verify that this is the case - use the CLR Profiler. It sounds like you have already done this.

While this isn't really a "leak" - the Garbage Collector will eventually clean them up - this allocation pattern is undesirable in a game. See this blog post about two methods for dealing with garbage collection in a game. Method 1 is usually easier and provides better results - so I am discussing it here.

It is worth mentioning at this point that the GC on the PC is fast enough that allocations like this don't really matter. The GC will clean up tiny objects (like your temporary strings) with very little overhead.

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

How do we fix this?

The answer is simple: DrawString will accept an instance of StringBuilder in place of string. Create one instance of StringBuilder and then reuse it each time you need to put together a custom string.

Note that converting a number or other object to a string, implicitly or by its ToString() method will also cause allocations. So you might have to write your own custom code to append to StringBuilder without causing allocations.

Here is one I use, in the form of an extension method, for appending integers to a string without allocating:

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;
    }
}



回答2:


There are no memory leaks in C# (or well, they're very difficult to get). What you are experiencing is normal. The garbage collector doesn't "feel" like it needs to collect memory, so it does not. Whenever memory runs short, garbage collection will occur. If you're absolutely certain that you aren't keeping unneeded references to your strings, then everything's fine.

If you want to force a GC cycle use GC.Collect().



来源:https://stackoverflow.com/questions/10923246/c-xna-giant-memory-leak

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!