Kir*_*ner 3 c# xna memory-leaks
这是我在此的头一篇博文.我正在使用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);
Run Code Online (Sandbox Code Playgroud)
然后每次调用都会在每次运行时在背后创建新对象string和StringBuilder对象.因为它们在你的Draw方法中,每个可能每秒运行60次.这是分配了很多临时对象!
要验证是否是这种情况,请使用CLR Profiler.听起来你已经做到了这一点.
虽然这不是真正的"泄漏" - 垃圾收集器最终将清理它们 - 这种分配模式在游戏中是不可取的.请参阅此博客文章,了解有关处理游戏中垃圾收集的两种方法.方法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;
}
}
Run Code Online (Sandbox Code Playgroud)