Поделиться через


Компиляция ReadyToRun

Время запуска и задержка приложения .NET можно улучшить, скомпилируя сборки приложения в формате ReadyToRun (R2R). R2R является разновидностью компиляции AOT.

Бинарные файлы R2R повышают производительность при запуске, снижая объем работы, выполняемой на этом этапе компилятором JIT. Бинарные файлы содержат такой же машинный код, который создается компилятором JIT. Но бинарные файлы R2R имеют больший размер, так как содержат не только код на промежуточном языке (IL), который по-прежнему необходим для некоторых сценариев, но и версию того же кода на машинном языке. R2R доступен только при публикации приложения, предназначенного для определенных сред выполнения (RID), таких как Linux x64 или Windows x64.

Чтобы скомпилировать проект как ReadyToRun, приложение должно быть опубликовано со свойством PublishReadyToRun, равным true.

Существует два способа публикации приложения в виде ReadyToRun:

  1. Укажите флаг PublishReadyToRun прямо в команду dotnet publish. Дополнительные сведения см. в dotnet publish .

    dotnet publish -c Release -r win-x64 -p:PublishReadyToRun=true
    
  2. Укажите свойство в проекте.

    • <PublishReadyToRun> Добавьте параметр в проект.
    <PropertyGroup>
      <PublishReadyToRun>true</PublishReadyToRun>
    </PropertyGroup>
    
    • Опубликуйте приложение без специальных параметров.
    dotnet publish -c Release -r win-x64
    

Влияние использования функции ReadyToRun

Компиляция на этапе предварительного времени имеет сложное влияние на производительность приложений, что может быть сложно предсказать. Как правило, размер сборки увеличится от двух до трех раз. Это увеличение физического размера файла может снизить производительность загрузки сборки с диска и увеличить рабочий набор процесса. Однако в результате количество методов, скомпилированных во время выполнения программы, обычно значительно уменьшается. Результатом является то, что большинство приложений с большим количеством кода получают большие преимущества производительности от включения ReadyToRun. Приложения, имеющие небольшие объемы кода, скорее всего, не будут иметь значительного улучшения от включения ReadyToRun, так как библиотеки среды выполнения .NET уже предварительно компилированы с ReadyToRun.

Улучшение запуска, описанное здесь, применяется не только к запуску приложения, но и к первому использованию любого кода в приложении. Например, ReadyToRun можно использовать для уменьшения задержки ответа первого использования веб-API в приложении ASP.NET.

Взаимодействие с многоуровневой компиляцией

Заранее созданный код не так оптимизирован, как код, созданный JIT. Для решения этой проблемы многоуровневая компиляция заменит часто используемые методы ReadyToRun с помощью методов, созданных JIT.

Как выбран набор предварительно скомпилированных сборок?

Пакет SDK предварительно компилирует сборки, распределенные с приложением. Для автономных приложений этот набор сборок будет включать платформу. Двоичные файлы C++/CLI не поддерживают компиляцию для ReadyToRun.

Чтобы исключить определенные сборки из обработки ReadyToRun, используйте <PublishReadyToRunExclude> список.

<ItemGroup>
  <PublishReadyToRunExclude Include="Contoso.Example.dll" />
</ItemGroup>

Как выбран набор методов для предварительной компиляции?

Компилятор попытается предварительно скомпилировать столько методов, сколько это возможно. Однако по разным причинам не ожидается, что использование функции ReadyToRun предотвратит выполнение JIT-файла. Такие причины могут включать в себя, но не ограничиваются следующими причинами:

  • Использование универсальных типов, определенных в отдельных сборках.
  • Взаимодействие с нативным кодом.
  • Использование аппаратных встроенных функций, которые компилятор не может доказать, что их безопасно использовать на целевом компьютере.
  • Некоторые необычные шаблоны IL.
  • Динамическое создание методов с помощью отражения или LINQ.

Создание символов для использования с профилировщиками

При компиляции приложения с помощью ReadyToRun профилировщики могут требовать символы для проверки созданных файлов ReadyToRun. Чтобы активировать создание символов, укажите свойство <PublishReadyToRunEmitSymbols>.

<PropertyGroup>
  <PublishReadyToRunEmitSymbols>true</PublishReadyToRunEmitSymbols>
</PropertyGroup>

Эти символы будут помещены в каталог публикации, и для Windows расширение файла будет .ni.pdb, а для Linux — .r2rmap. Эти файлы обычно не распространяются для конечных клиентов, но вместо этого обычно хранятся на сервере символов. Как правило, эти символы полезны для отладки проблем с производительностью, связанных с запуском приложений, так как многоуровневая компиляция заменит созданный код ReadyToRun динамически созданным кодом. Однако при попытке профилировать приложение, которое отключает многоуровневую компиляцию , символы будут полезны.

Составной элемент ReadyToRun

Обычная компиляция ReadyToRun создает двоичные файлы, которые можно обслуживать и управлять по отдельности. Начиная с .NET 6 добавлена поддержка составной компиляции ReadyToRun. Композитный ReadyToRun компилирует набор сборок, которые должны распространяться вместе. Это имеет преимущество, что компилятор может выполнять более эффективную оптимизацию и сокращает набор методов, которые нельзя скомпилировать с помощью процесса ReadyToRun. Однако, как компромисс, скорость компиляции значительно уменьшается, и общий размер файла приложения значительно увеличивается. Из-за этих компромиссов рекомендуется использовать составной readyToRun только для приложений, которые отключают многоуровневую компиляцию или приложения, работающие в Linux, которые ищут оптимальное время запуска с автономным развертыванием. Чтобы включить составную компиляцию ReadyToRun, укажите <PublishReadyToRunComposite> свойство.

<PropertyGroup>
  <PublishReadyToRunComposite>true</PublishReadyToRunComposite>
</PropertyGroup>

Замечание

В .NET 6 составная команда ReadyToRun поддерживается только для автономного развертывания.

Ограничения при работе с несколькими платформами и архитектурами

Для некоторых платформ SDK компилятор ReadyToRun может выполнять перекрестную компиляцию для других целевых платформ.

Поддерживаемые целевые объекты компиляции описаны в таблице ниже при выборе версий .NET 6 и более поздних версий.

Платформа SDK Поддерживаемые целевые платформы
Windows X64 Windows (X86, X64, Arm64), Linux (X64, Arm32, Arm64), macOS (X64, Arm64)
Windows X86 Windows (X86), Linux (Arm32)
Linux X64 Linux (X64, Arm32, Arm64), macOS (X64, Arm64)
Linux Arm32 Linux Arm32
Linux Arm64 Linux (X64, Arm32, Arm64), macOS (X64, Arm64)
macOS X64 Linux (X64, Arm32, Arm64), macOS (X64, Arm64)
macOS Arm64 Linux (X64, Arm32, Arm64), macOS (X64, Arm64)

Поддерживаемые целевые объекты компиляции описаны в таблице ниже при выборе .NET 5 и ниже.

Платформа SDK Поддерживаемые целевые платформы
Windows X64 Windows X86, Windows X64, Windows Arm64
Windows X86 Windows X86, Windows Arm32
Linux X64 Linux X86, Linux X64, Linux Arm32, Linux Arm64
Linux Arm32 Linux Arm32
Linux Arm64 Linux Arm64
macOS X64 macOS X64