В настоящее время я портирую приложение VS2005 C ++ с CE5 на CE6 и испытываю серьезные проблемы с производительностью. Это настолько далеко, что один запрос HTTP, извлекающий динамическое содержимое, занимает 40 мс на CE5 и 350 мс на CE6. Эти значения были хуже из-за множества неэффективностей, которые я уже исправил, улучшая производительность в обеих системах, но в данный момент я застрял в этой задержке. Напомним, что оба теста выполняются на одной и той же машине, и веб-сервер поставляется не с CE, а с пользовательским, реализованным на C ++. Также обратите внимание, что проблема заключается не в сетевом вводе-выводе, CE6 даже превосходит CE5 на той же машине при обслуживании статических файлов, а в динамической обработке контента.
Пытаясь выяснить, почему программа работает так плохо, я наткнулся на то, что меня озадачило: в CE5 Interlocked * API для x86 не использует ни встроенные функции компилятора, ни реальные вызовы функций, а встроенный код сборки. В этом коде есть комментарий о том, что встроенная функция включает префиксы блокировок, которые требуются только для многопроцессорных систем и которые замедляют работу кода только на одном ядре, таком как CE5. На CE6 эти функции реализованы с использованием встроенных функций компилятора, включая префикс блокировки. Поскольку эти функции используются, например, Boost и STLport, оба из которых используются внутри веб-сервера, мне было интересно, могут ли они быть виновником.
Еще одна вещь, которую я заметил, заключалась в том, что некоторые функции разбора строк занимают очень много времени. Хуже того, кажется, что вызов той же функции во второй раз после первого занимает меньше времени, поэтому создается впечатление, что происходит какое-то кэширование. Так как это короткий (<1kB) строка, полученная через TCP, которая анализируется в памяти, я не могу представить, какой кеш может быть ответственным за это. Единственным кешем может быть кеш инструкций, но программа не больше, чем версия CE5, и если код выполняется из не кэшированной памяти, он не будет показывать эти эффекты кеширования.
TLDR — Вопросы:
Резюме Нет проблем, которые зависят от исполняемого файла, не говоря уже о Interlocked API. Запуск того же исполняемого файла доказал это. Однако работа на другой машине с другой настройкой платформы имела значение. Теперь мы вернулись к Platform Builder, пытаясь выяснить различия между двумя платформами.
Нет. WEC7 требуется для поддержки SMP. Скорее всего, в CE6 OEM отключил другие ядра.
Ни о чем я не знаю.
Либо использовать инструменты профилирования производительности или прибавьте к своему коду кодовые звонки, чтобы сузить место, где дела идут слишком долго.
Я наконец нашел причину поведения производительности, это просто пейджинг. У CE6 есть менеджер пула (см. http://blogs.msdn.com/b/ce_base/archive/2008/01/19/paging-and-the-windows-ce-paging-pool.aspx), который обрабатывает подкачку неиспользуемых отображенных DLL и EXE-файлов. Когда количество отображаемых двоичных файлов превышает определенный размер, он начинает (с низким приоритетом) выгружать память. Ограничение при запуске подкачки по умолчанию составляет всего 3 МБ, что довольно мало для современных приложений. Кроме того, кеш — это не кэш LRU, а просто отбрасывает страницы в порядке их загрузки.
Оказывается, что наша система превысила этот предел, что вызывает пейджинг. Из-за используемого алгоритма он всегда выбрасывает использованные, которые затем нужно будет снова ввести. Код, который обслуживает статические файлы, невелик, поэтому это ограничение не сильно повлияло на это. Однако код, обслуживающий динамические страницы, гораздо больше, поэтому он вводит хаос в общую систему с помощью ввода-вывода. Это также объясняет, почему проблему нельзя отнести к определенному коду, это был не сам код, а его загрузка.
Я обнаружил это через IOCTL_HAL_GET_POOL_PARAMETERS, который дал мне соответствующие параметры конфигурации, текущее состояние, как часто выполнялся поток выгрузки и как долго (хотя последний — только время, которое потребовалось для замены страниц). Я должен быть в состоянии найти возникающие ошибки страниц в трекере ядра тоже теперь, когда я знаю, что я ищу. Я также мог заметить, что индикатор активности на адаптере CF-карты теперь загорается при первой загрузке файла, но не при последующих запросах, когда он берется из кэша. Это всегда вызывало мигание светодиода на динамических страницах.
Простое решение — увеличить лимит для менеджера пула, чтобы он не начал выбрасывать вещи. Это можно легко сделать в config.bib, исправив kernel.dll с соответствующими значениями. Кроме того, может помочь уменьшение размера исполняемого файла, но это не так просто.