WP7 C#/ XNA中的可变字符串?

时间:2011-09-08 18:00:47

标签: c# windows-phone-7 garbage-collection xna

我正在开发Windows Phone 7 XNA游戏。它是用C ++编写的游戏的一个端口,因此,我试图尽可能少地重写游戏代码。

垃圾是WP7上的一个巨大的问题,因为收集器是非代数且速度慢的,所以一个集合(每1MB触发一次)每MB分配大约需要10毫秒。我完全打算使用最大可用的90MB,所以我们每隔MB分配一个~900ms的停止。

我已经能够重做工作,所以我们没有每帧生成垃圾,除了一些字符串的情况。

似乎StringBuilder.ToString()生成了垃圾,而here描述的方法在WP7上不起作用。

我需要做的两件事是:

  • 将分钟/秒/ hundreths格式化为mm:ss.hh以显示在屏幕上。显然,我可以使用StringBuilder(使用不会通过填充整数创建垃圾的扩展方法)并使用SpriteBatch直接显示StringBuilder。
  • 将“foo.bar.baz.qux”形式的字符串拆分为“。”上的数组,即{“foo”,“bar”,“baz”,“qux”}并复制一个元素时间进入一个字符串数组。这用于设置游戏角色的层次状态。它也几乎直接从原始游戏移植过来,而且很大程度上依赖于它以这种方式工作。我真的想避免重写它。

没有将大量代码转换为使用char []而不是字符串,有没有办法在C#中拥有真正无垃圾的可变字符串?

2 个答案:

答案 0 :(得分:10)

为什么首先需要将StringBuilder转换为String?如您所知,您可以将StringBuilder直接传递给XNA的绘图方法。您还可以使用StringBuilder来检索子字符串:

substringBuilder.Length = 0;
for (int i = start; i <= end; i++)
    substringBuilder.Append(originalBuilder[i]);

StringBuilder ToString()AppendFormat()唯一要避免的事情。没有其他格式化方法(据我所知)生成垃圾。 更新:我错了。编写自己的扩展方法。此处提供了一个简介:Avoiding garbage when working with StringBuilder

编写一个将字符串拆分为基于给定分隔符的子字符串的方法相对容易。请记住,String.Split()对于两个的原因是邪恶的 - 首先,因为它分配了新的字符串;第二,因为它分配一个新数组。字符串的不变性只是你问题的一半。

考虑StringBuilder的以下扩展方法。我还没有彻底测试过这段代码,但它应该给你一个大致的想法。请注意,它希望您传入一个预先分配的数组,然后填充它。

public static void Substring(this StringBuilder source, Int32 start, Int32 count, StringBuilder output)
{
    output.Length = 0;
    for (int i = start; i < start + count; i++)
    {
        output.Append(source[i]);
    }
}

public static int Split(this StringBuilder source, Char delimiter, StringBuilder[] output)
{
    var substringCount = 0;
    var substringStart = 0;
    for (int i = 0; i < source.Length; i++)
    {
        if (source[i] == delimiter)
        {
            source.Substring(substringStart, i - substringStart, output[substringCount]);
            substringCount++;
            substringStart = i + 1;
        }
    }
    if (substringStart < source.Length - 1)
    {
        source.Substring(substringStart, source.Length - substringStart, output[substringCount]);
        substringCount++;
    }
    return substringCount;
}

答案 1 :(得分:0)

  

我试图尽可能少地重写游戏代码。

小心,重写可能需要更长时间。 Cole Campbell是对的,在你想要绘制ToString()时没有任何意义。 XNA有draw方法,它采用StringBuldier,在我的游戏中运行良好。

您问题的另一个解决方案:创建字符串的全局HashSet并在加载游戏或级别时设置它以避免收集压力。

加载游戏时尽量做到尽可能多。