Статьи

Важность тестирования производительности в приложении Windows Phone 7

Несколько месяцев я описывал, как я справился с ошибкой кодирования элемента управления WebBrowser в WP7 . К сожалению, это была проблема не только со «умными цитатами», но и со всеми незападными символами, и наивное решение проблемы вызвало проблему с производительностью. Посмотрим, как я это решил.

Эта проблема

Мне нужна была процедура замены символов более общего назначения, например, вторая, о которой я упоминал в предыдущем посте :

foreach (char value in strText)
{
    int decValue = int.Parse(string.Format("{0:x4}", (int)value), 
        System.Globalization.NumberStyles.HexNumber);
    txtUnicode = txtUnicode + "&#" + decValue+ ";";
}

Но у этого были две проблемы (одна «косметическая», а другая более серьезная в отношении выступлений):

  1. если сообщение написано на западном языке, оно заменит много символов, которые не нужно будет заменять
  2. это объединяет укусы, и поскольку сообщение может быть также довольно большим, это приводит к огромным потерям производительности. Я усвоил этот трудный путь, посмотрев, сколько времени потребовалось FeedTso для отображения длинных постов ( версия FeedTso, которая решает эту проблему, была представлена ​​и скоро будет доступна на MarketPlace )

Решение

Поэтому я создал оптимизированную версию, которая просто заменяет символы, которые не могут корректно отображаться элементом управления WebBrowser, и использует вместо StringBuilder вместо прямой конкатенации строк.

public static string EncodeToUnicodeBuilder(this string strText)
{
    string chararray =
        " `1234567890-=qwertyuiop[]\\asdfghjkl;'"+
        "zxcvbnm,./~!@#$%^&*()_+QWERTYUIO"+
        "P{}|ASDFGHJKL:\"ZXCVBNM<>?";
    StringBuilder builder = new StringBuilder();
    foreach (char value in strText)
    {
        if (chararray.IndexOf(value) >= 0)
        {
            builder.Append(value);
        }
        else
        {
            int decValue = int.Parse(string.Format("{0:x4}", (int)value),
                                        System.Globalization.NumberStyles.HexNumber);
            builder.Append("&#" + decValue.ToString() + ";");
        }
    }
    return builder.ToString();
}

Улучшения производительности

Улучшение скорости впечатляет: в стандартном английском посте размером около 6 КБ (который, вероятно, потребовал очень мало замен, если вообще не было замены), я получил улучшение скорости в 120 раз .

И с текстом аналогичной длины, но требующим гораздо большего количества замен (японский пост), улучшение почти в 2 раза .

Как вы можете видеть, японский текст нуждается в большем количестве замен, но фильтрация символов ASCII дает увеличение скорости в 1,3 раза , но после добавления StringBuilder общее усиление по-прежнему составляет 19x .

Тестирование на WP7

Эти тесты выполнялись на консольном приложении, работающем на моей машине разработчика. Я также запускал одинаковые тесты как на эмуляторе, так и на реальном устройстве (Samsung Omnia 7).

Как вы уже могли догадаться, работа в эмуляторе медленнее, чем в консольном приложении, а реальное устройство — еще медленнее. И результаты еще более впечатляющие: замена только необходимых символов и использование StringBuilder позволили повысить производительность в 130 раз .

Цифры

И вот результаты всех тестов, использующих наивную версию (замените все, используя конкатенацию) в качестве базового результата:

  Заменить все Заменить только не ASCII Не ASCII + StringBuilder
Консольное приложение (EN) 56ms 6x (9,21мс) 121x (0,46мс)
Консольное приложение (JP) 45ms 1,3x (34мс) 19x (2,33мс)
Эмулятор 267ms 5,8x (46мс) 73x (3,7 мс)
Эмулятор (JP) 215ms 1,4x (154мс) 15x (14мс)
Устройство (EN) 1,45 сек 5x (275 мс) 131x (11,1мс)
Устройство (JP) 1,22 сек 1,2x (1,02сек) 17x (69,4 мс)

Здесь вы можете скачать тестовое приложение (как для консоли, так и для версии WP7).

Чему я научился из этого?

Это еще одно доказательство того, что вы никогда не должны использовать простую конкатенацию строк, когда вам нужно сделать больше, чем несколько конкатенаций. Всегда используйте StringBuilder . Это даже более важно в устройстве WP7, которое в 25 раз медленнее, чем консольное приложение, и неоптимизированная версия занимает больше секунды вместо 1/100 секунды.