Несколько месяцев я описывал, как я справился с ошибкой кодирования элемента управления WebBrowser в WP7 . К сожалению, это была проблема не только со «умными цитатами», но и со всеми незападными символами, и наивное решение проблемы вызвало проблему с производительностью. Посмотрим, как я это решил.
Эта проблема
Мне нужна была процедура замены символов более общего назначения, например, вторая, о которой я упоминал в предыдущем посте :
foreach (char value in strText)
{
int decValue = int.Parse(string.Format("{0:x4}", (int)value),
System.Globalization.NumberStyles.HexNumber);
txtUnicode = txtUnicode + "&#" + decValue+ ";";
}
Но у этого были две проблемы (одна «косметическая», а другая более серьезная в отношении выступлений):
- если сообщение написано на западном языке, оно заменит много символов, которые не нужно будет заменять
- это объединяет укусы, и поскольку сообщение может быть также довольно большим, это приводит к огромным потерям производительности. Я усвоил этот трудный путь, посмотрев, сколько времени потребовалось 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 секунды.