这是我的第一篇帖子。
我正在使用XNA在Visual Studio 2010中制作游戏,但遇到了一个大内存泄漏问题。游戏开始时使用17k RAM,十分钟后达到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);
string
和StringBuilder
对象。因为它们位于你的Draw
方法中,所以每个方法可能每秒运行60次。这将分配大量临时对象!DrawString
将在string
的位置接受StringBuilder
的实例。创建一个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;
}
}
Append
比在缓冲区中构建字符串并将其放置在原处要快一些,但请注意算法是从右到左构建字符串的。我会留下一个练习来解决从左到右的算法;) 此外:不必担心EnsureCapacity
。这里的整个重点是重复使用缓冲区。因此,容量增加只会发生一次。而且CPU时间差异非常小。这是一种特定的GC优化。在其上添加不必要的额外优化是不好的做法。 - Andrew Russellstring
引用,那么一切都很好。GC.Collect()
。GC.Collect
不是一个好主意,最好在游戏循环内使用对象池,并避免动态分配。 - Daniel Little