C#/XNA 巨大的内存泄漏

标签 c# memory-leaks xna

这是我在这里的第一篇文章。 我正在使用 XNA 在 Visual Studio 2010 中制作游戏,但遇到了巨大的内存泄漏。我的游戏开始时使用 17k 内存,然后在十分钟后达到 65k。我运行了一些内存分析器,它们都说正在创建 String 对象的新实例,但它们并不存在。 String 的事件实例数量根本没有改变。它还创建了 Char[](我希望从中得到)、Object[] 和 StringBuilder 的实例。我的游戏很新,但是这里要发布的代码太多了。我不知道如何摆脱不活跃的实例,请帮忙!

最佳答案

您发布的信息不足,无法提供有根据的猜测。这是我有根据的猜测:

如果您在 Draw 方法中做这样的事情:

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 次。那是分配了很多临时对象!

要验证情况是否如此 - 使用 CLR Profiler。听起来您已经这样做了。

虽然这并不是真正的“泄漏”——垃圾收集器最终会清理它们——但这种分配模式在游戏中是不可取的。参见 this blog post关于在游戏中处理垃圾收集的两种方法。方法 1 通常更简单并且提供更好的结果 - 所以我在这里讨论它。

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

另一方面,在 Xbox 360 上,即使像这样定期产生少量垃圾也会导致一些严重的性能问题。 (我不确定 WP7,但我个人会像对待 Xbox 一样对待它——小心!)

我们如何解决这个问题?

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

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

这是我以扩展方法的形式使用的一种方法,用于在不分配的情况下将整数附加到字符串:

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 巨大的内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10923246/

相关文章:

C# 停止选择一个或多个 TreeNodes 的 Treeview

c# 在 MS Word 中比较样式对象

c# - 我如何检查 DateTime 是否为空

c# - XNA 4.0 和效果代码

c# - XNA:激活一个声音实例仅需激活一次

c# - 从 c# 代码传递结构引用以调用在其原型(prototype)中接受结构引用的 c++ DLL 函数

ios - 当 Leaks 工具不显示内存泄漏时如何调试它们?

c++ - 堆栈分配的数组是否可能发生内存泄漏?

ios - 将图像加载到 UITableView 中的自定义单元格时发生内存泄漏

c# - XNA 是否提供音频输入(线路输入)?