Переменные строки в WP7 С#/XNA?

Я работаю над игрой Windows Phone 7 XNA. Это порт игры, написанный на С++, и как таковой, я стараюсь как можно меньше переписывать код геймплея.

Мусор - это огромная проблема для WP7, потому что сборщик является негенеративным и медленным, поэтому сбор (который запускается каждые 1 МБ) занимает около 10 мс на МБ распределений. Я полностью намерен использовать максимально доступный 90 МБ, поэтому мы смотрим на 900 мс, останавливая каждый МБ размещения.

Я смог переделать вещи так, чтобы у нас не было мусора, созданного за кадр, за исключением нескольких случаев строк.

Кажется, что StringBuilder.ToString() генерирует мусор, а метод, описанный здесь, не работает на WP7.

Мне нужно сделать две вещи:

  • Отформатируйте минуты/секунды/hundreths как mm: ss.hh для отображения на экране. По-видимому, я могу сделать это с помощью StringBuilder (используя методы расширения, которые не создают мусор из бокса в int) и отображать StringBuilder напрямую с помощью SpriteBatch.
  • Разделите строку формы "foo.bar.baz.qux" на массив на ".", то есть { "foo", "bar", "baz", "qux" } и скопируйте один элемент на время в массив строк. Это для установки иерархического состояния игровых игроков. Он также почти полностью переносится из оригинальной игры и совсем немного зависит от того, как он работает именно так. Я бы очень хотел, чтобы не переписывать его.

За исключением преобразования большого количества кода для использования char [] вместо строки, есть ли способ иметь действительно мусорные переменные строки в С#?

Ответ 1

Зачем вам нужно преобразовать StringBuilder в String в первую очередь? Как вы уже отметили, вы можете передать StringBuilder непосредственно в методы рисования XNA. Вы также можете использовать StringBuilder для получения подстрок:

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

Единственными вещами, которые вы хотите избежать с помощью StringBuilder, являются ToString() и AppendFormat(). Ни один из других методов форматирования (насколько мне известно) не генерирует мусор. Обновление: я ошибся. Напишите свои собственные методы расширения. Сводка доступна здесь: Избегайте мусора при работе с 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;
}

Ответ 2

Я стараюсь как можно меньше переписывать код геймплея.

Осторожно, что может потребоваться больше времени, чтобы переписать. Коул Кэмпбелл прав, нет смысла вызывать ToString(), пока вы хотите его нарисовать. XNA имеет метод draw, который принимает StringBuldier, и он хорошо работает в моей игре.

Еще одно решение вашей проблемы: создайте глобальную HashSet своих строк и настройте ее, когда вы загружаете игру или уровень, чтобы избежать сбора давления.

Постарайтесь делать как можно больше, когда вы загружаете игру.