C#/XNA巨型内存泄漏 [英] C#/XNA Giant Memory Leak

查看:79
本文介绍了C#/XNA巨型内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我在这里的第一篇文章. 我正在使用XNA在Visual Studio 2010中制作游戏,但遇到了巨大的内存泄漏.我的游戏开始时使用17k内存,十分钟后达到65k.我运行了一些内存事件探查器,他们都说正在创建String对象的新实例,但它们并不存在. String的活动实例的数量完全没有改变.它还在创建Char [](我期望它),Object []和StringBuilder的实例.我的游戏非常新,但是要在此处发布太多代码.我不知道如何清除不活跃的实例,请帮忙!

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!

推荐答案

您没有发布足够的信息来为您提供更多的有根据的猜测.这是我的有根据的猜测:

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

如果您在Draw方法中执行以下操作:

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

然后,每次调用时,每个调用都会在您的背后创建新的stringStringBuilder对象.因为它们在您的Draw方法中,所以它们每个可能每秒运行60次.分配了很多临时对象!

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!

要验证是这种情况,请使用CLR事件探查器.听起来您已经这样做了.

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

虽然这并不是一个真正的泄漏"-垃圾收集器最终会清理它们-这种分配模式在游戏中是不可取的.参见此博客中介绍了两种处理游戏中垃圾收集的方法.方法1通常更容易且可提供更好的结果-因此,我在这里进行讨论.

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.

在这一点上值得一提的是,PC上的GC足够快,以至于这样的分配并不重要. GC将以很少的开销清理微小的对象(例如您的临时字符串).

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.

另一方面,在Xbox 360上,即使定期产生少量垃圾也可能导致严重的性能问题. (我不确定WP7,但我会谨慎对待它,就像Xbox一样!)

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!)

我们如何解决此问题?

答案很简单:DrawString将接受StringBuilder的实例代替string.创建StringBuilder的一个实例,然后在每次需要组合自定义字符串时重新使用它.

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.

请注意,将数字或其他对象隐式地或通过其ToString()方法转换为字符串也将导致分配.因此,您可能必须编写自己的自定义代码以附加到StringBuilder而不引起分配.

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

这篇关于C#/XNA巨型内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆