Подтвердить что ты не робот

Что делает запуск приложений WPF медленным?

Я заметил, что запуск приложения WPF иногда довольно медленный. Кто-нибудь знает, является ли причиной инициализация элементов или загрузка DLL или что-то еще?

4b9b3361

Ответ 1

Текст ниже был извлечен из этой статьи MSDN об улучшении времени запуска приложений WPF (Edit: теперь объединено в Время запуска приложения WPF)

Время запуска приложения

Время, необходимое для запуска приложения WPF, может сильно различаться. В этом разделе описываются различные методы сокращения воспринимаемого и фактического времени запуска приложения Windows Presentation Foundation (WPF).

Понимание холодного запуска и WarmStartup

Холодный запуск происходит, когда ваше приложение запускается в первый раз после перезагрузки системы или при запуске приложения закрывает его, а затем запускает его снова через долгое время. Когда приложение запускается, если требуемые страницы (код, статические данные, реестр и т.д.) Не присутствуют в резервном списке диспетчера памяти Windows, возникают сбои страниц. Для доступа к страницам требуется доступ к диску.

Теплый запуск происходит, когда большая часть страниц для основных компонентов среды CLR уже загружена в память, что экономит дорогое время доступа к диску. Вот почему управляемое приложение запускается быстрее, когда оно выполняется во второй раз.

Внедрить экран заставки

В случаях, когда существует значительная, неизбежная задержка между запуском приложения и отображением первого пользовательского интерфейса, оптимизируйте предполагаемое время запуска с помощью заставки. Этот подход отображает изображение почти сразу после запуска пользователем приложения. Когда приложение готово отобразить свой первый пользовательский интерфейс, заставка замирает. Начиная с .NET Framework 3.5 SP1, вы можете использовать класс SplashScreen для реализации заставки. Для получения дополнительной информации см. Как добавить всплывающий экран в приложение WPF.

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

Анализ кода запуска

Определите причину медленного холодного запуска. Дисковый ввод-вывод может быть ответственным, но это не всегда так. В общем, вы должны минимизировать использование внешних ресурсов, таких как сеть, веб-службы или диск.

Перед тестированием убедитесь, что другие запущенные приложения или службы не используют управляемый код или код WPF.

Запустите приложение WPF сразу после перезагрузки и определите, сколько времени требуется для отображения. Если все последующие запуски вашего приложения (теплый запуск) намного быстрее, проблема с холодным запуском, скорее всего, вызвана I/O.

Если проблема холодного запуска приложения не связана с I/O, вполне вероятно, что ваше приложение выполняет длительную инициализацию или вычисление, ждет завершения какого-либо события или требует много компиляции JIT при запуске. В следующих разделах более подробно описаны некоторые из этих ситуаций.

Оптимизация загрузки модуля

Используйте инструменты, такие как Process Explorer (Procexp.exe) и Tlist.exe, чтобы определить, какие модули загружаются вашим приложением. Команда Tlist <pid> показывает все модули, загруженные процессом.

Например, если вы не подключаетесь к Интернету и вы видите, что загружается System.Web.dll, в вашем приложении есть модуль, который ссылается на эту сборку. Убедитесь, что ссылка нужна.

Если ваше приложение имеет несколько модулей, объедините их в один модуль. Такой подход требует меньших затрат на сборку. Меньшее количество сборок также означает, что CLR поддерживает меньшее состояние.

Операции инициализации отсрочки

Рассмотрим перенос кода инициализации до тех пор, пока не будет показано главное окно программы.

Имейте в виду, что инициализация может выполняться внутри конструктора класса, а если код инициализации ссылается на другие классы, это может вызвать каскадный эффект, при котором выполняются многие конструкторы классов.

Избегать конфигурации приложения

Попробуйте избежать настройки приложения. Например, если приложение имеет простые требования к конфигурации и имеет строгие цели времени запуска, записи реестра или простой файл INI могут быть более быстрой альтернативой запуска.

Используйте GAC

Если сборка не установлена ​​в глобальном кэше сборок (GAC), есть задержки, вызванные хеш-проверкой сильных имен сборок и проверкой изображений Ngen, если на компьютере доступно собственное изображение для этой сборки. Проверка строгого имени пропускается для всех сборок, установленных в GAC. Для получения дополнительной информации см. Gacutil.exe(Глобальный инструмент кэширования сборок).

Использовать Ngen.exe

Рассмотрите возможность использования генератора собственных изображений (Ngen.exe) в своем приложении. Использование Ngen.exe означает торговое потребление процессора для большего доступа к диску, поскольку собственное изображение, созданное Ngen.exe, скорее всего будет больше, чем изображение MSIL.

Чтобы улучшить время запуска, вы всегда должны использовать Ngen.exe в своем приложении, потому что это позволяет избежать затрат ЦП на компиляцию JIT кода приложения.

В некоторых сценариях с холодным запуском использование Ngen.exe также может быть полезно. Это связано с тем, что компилятор JIT (mscorjit.dll) не нужно загружать.

Наличие модулей Ngen и JIT может иметь наихудший эффект. Это связано с тем, что mscorjit.dll должен быть загружен, а когда JIT-компилятор работает с вашим кодом, многие страницы в изображениях Ngen должны быть доступны, когда компилятор JIT считывает метаданные сборок.

Ngen и ClickOnce

То, как вы планируете развертывать свое приложение, также может повлиять на время загрузки. Развертывание приложения ClickOnce не поддерживает Ngen. Если вы решили использовать Ngen.exe для своего приложения, вам придется использовать другой механизм развертывания, например установщик Windows.

Для получения дополнительной информации см. Ngen.exe(Генератор собственных изображений).

Коллизии адресов репозиции и DLL

Если вы используете Ngen.exe, имейте в виду, что перезагрузка может произойти, когда исходные изображения загружаются в память. Если DLL не загружается на своем предпочтительном базовом адресе, потому что этот диапазон адресов уже выделен, загрузчик Windows загрузит его по другому адресу, что может быть трудоемкой операцией.

Вы можете использовать инструмент Virtual Address Dump (Vadump.exe), чтобы проверить, есть ли модули, в которых все страницы являются закрытыми. Если это так, возможно, модуль был переустановлен на другой адрес. Поэтому его страницы не могут быть разделены.

Подробнее о том, как установить базовый адрес, см. Ngen.exe(Генератор собственных изображений).

Оптимизировать аутентификационный код

Проверка подлинности подтверждается добавлением времени запуска. Аутентифицированные сборки должны быть проверены с помощью центра сертификации (CA). Эта проверка может занять много времени, поскольку она может потребовать подключения к сети несколько раз для загрузки текущих списков отзыва сертификатов. Он также гарантирует, что существует целая цепочка действительных сертификатов на пути к доверенному корню. Это может перевести на несколько секунд задержки при загрузке сборки.

Рассмотрите возможность установки сертификата CA на клиентском компьютере или избегайте использования Authenticode, когда это возможно. Если вы знаете, что ваша заявка не нуждается в доказательствах издателя, вам не нужно оплачивать стоимость проверки подписи.

Начиная с .NET Framework 3.5, существует опция конфигурации, которая позволяет обойти проверку подлинности. Для этого добавьте следующий параметр в файл app.exe.config:

<configuration>
 <runtime>
    <generatePublisherEvidence enabled="false"/>
  </runtime>
</configuration>

Сравнение производительности в Windows Vista​​b >

Менеджер памяти в Windows Vista имеет технологию SuperFetch. SuperFetch анализирует модели использования памяти с течением времени для определения оптимального содержимого памяти для конкретного пользователя. Он постоянно работает, чтобы поддерживать этот контент во все времена.

Этот подход отличается от метода предварительной выборки, используемого в Windows XP, который предварительно загружает данные в память без анализа шаблонов использования. Со временем, если пользователь часто использует ваше приложение WPF в Windows Vista, время запуска вашего приложения может улучшиться.

Эффективно использовать AppDomains

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

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

Использовать атрибут NeutralResourcesLanguage

Используйте NeutralResourcesLanguageAttribute, чтобы указать нейтральную культуру для ResourceManager. Такой подход позволяет избежать неудачных сборок.

Используйте класс BinaryFormatter для сериализации

Если вы должны использовать сериализацию, используйте BinaryFormatter вместо XmlSerializer. Класс BinaryFormatter реализован в библиотеке базового класса (BCL) в сборке mscorlib.dll. XmlSerializer реализован в сборке System.Xml.dll, которая может быть дополнительной DLL для загрузки.

Если вы должны использовать класс XmlSerializer, вы можете добиться более высокой производительности, если предварительно создаете сборку сериализации.

Настройте ClickOnce для проверки обновлений после запуска

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

Если вы используете модель браузера XAML (XBAP), имейте в виду, что ClickOnce проверяет сайт развертывания на наличие обновлений, даже если XBAP уже находится в кеше ClickOnce. Для получения дополнительной информации см. Безопасность и развертывание ClickOnce.

Настроить службу PresentationFontCache для автоматического запуска

Первое приложение WPF для запуска после перезагрузки - это служба PresentationFontCache. Служба кэширует системные шрифты, улучшает доступ к шрифтам и улучшает общую производительность. При запуске службы есть накладные расходы, и в некоторых контролируемых средах подумайте о том, как настроить службу для автоматического запуска при перезагрузке системы.

Установите программную привязку данных

Вместо использования XAML для объявления DataContext декларативно для главного окна, подумайте о его программном программировании в OnActivated.

Ответ 2

Время запуска приложения WPF может быть намного быстрее, если вы используете Framework 3.51, а не 3.5 или 3.0. 3.51 действительно является улучшением.

Ответ 3

Что помогло мне больше всего из превосходной статьи, на которую ссылались Стюарт, был трюк XmlSerializer. Это действительно побрилось несколько секунд. Кроме того, не стоит недооценивать дефрагментацию вашего HD: -)

Ответ 4

Самый полезный совет по исправлению производительности запуска WPF, который я когда-либо видел, был дан в этом другом вопросе: запустите "ngen update" в каждой папке фрейма.

Похоже, что Microsoft не может обновлять свой ngen-кеш, что приводит к тому, что ваше приложение в значительной степени перекомпилирует половину платформы .NET при каждом запуске.

Трудно поверить, но кажется правдой.

Ответ 5

Это старый поток, но я несколько раз сталкивался с этим, пытаясь исправить проблему с загрузкой приложений WPF в моей системе Win10, поэтому я решил указать ответ, который может помочь другим - ответ который занимает ужасное 5-секундное время запуска для всех приложений WPF в этой системе всего за несколько миллисекунд. Удалите драйвер nVidia "3D Vision" . У меня есть карта GeForce GTX 650, и драйвер "3D Vision", похоже, не предлагает ничего полезного, поэтому удаление это не проблема для меня. Инструмент анализа производительности VisualStudio2015, наконец, помог показать, что почти все 5 секундное время запуска было потрачено IDLE после вызова через nvapi64.dll - драйвера nVidia. Ничего себе.