Изменяемые строки в WP7 C # / XNA? - PullRequest
10 голосов
/ 08 сентября 2011

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

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

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

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

Две вещи, которые мне нужно сделать:

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

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

Ответы [ 2 ]

10 голосов
/ 08 сентября 2011

Зачем вам нужно конвертировать 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;
}
0 голосов
/ 09 сентября 2011

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

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

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

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

...