Несколько месяцев я описывал, как я справился с ошибкой кодирования элемента управления 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 секунды.