ReadyToRun 編譯

將應用程式元件編譯為 ReadyToRun (R2R) 格式,即可改善 .NET 應用程式啟動時間和延遲。 R2R 是一種預先(AOT) 編譯。

R2R 二進位檔會透過減少 Just-In-Time (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 的大型效能優勢。 由於 .NET 執行時間程式庫已經使用 ReadyToRun 預先編譯,因此擁有少量程式碼的應用程式可能不會經歷大幅改善。

這裡討論的啟動改進不僅適用于應用程式啟動,也適用于應用程式中第一次使用任何程式碼。 例如,ReadyToRun 可用來減少 ASP.NET 應用程式中第一次使用 Web API 的回應延遲。

與階層式編譯的互動

預先產生的程式碼不如 JIT 所產生的程式碼高度優化。 為了解決此問題,階層式編譯會將常用的 ReadyToRun 方法取代為 JIT 產生的方法。

如何選擇一組先行編譯的元件?

SDK 會先行編譯與應用程式一起散發的元件。 對於獨立式應用程式,這組元件會包含架構。 C++/CLI 二進位檔不符合 ReadyToRun 編譯資格。

若要從 ReadyToRun 處理中排除特定元件,請使用 <PublishReadyToRunExclude> 清單。

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

要如何預先編譯一組方法?

編譯器會嘗試盡可能預先編譯許多方法。 不過,基於各種原因,不預期使用 ReadyToRun 功能會防止 JIT 執行。 這類原因可能包括,但不限於:

  • 使用不同的元件中定義的泛型型別。
  • 使用機器碼的 Interop。
  • 使用編譯器無法證明在目的電腦上使用的硬體內建函式是安全的。
  • 某些不尋常的 IL 模式。
  • 透過反映或 LINQ 建立動態方法。

用於分析工具的符號產生

使用 ReadyToRun 編譯應用程式時,分析工具可能需要符號來檢查產生的 ReadyToRun 檔案。 若要啟用符號產生,請 <PublishReadyToRunEmitSymbols> 指定 屬性。

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

這些符號會放在發行目錄中,而 Windows 的 副檔名為 .ni.pdb,而 Linux 的副檔名為 .r2rmap。 這些檔案通常不會轉散發給終端客戶,而是通常會儲存在符號伺服器中。 一般而言,這些符號對於偵錯與啟動應用程式相關的效能問題很有用,因為 階層式編譯 會將 ReadyToRun 產生的程式碼取代為動態產生的程式碼。 不過,如果嘗試分析停用 階層式編譯 的應用程式,符號將會很有用。

Composite ReadyToRun

一般 ReadyToRun 編譯會產生可個別服務及操作的二進位檔。 從 .NET 6 開始,已新增複合 ReadyToRun 編譯的支援。 Composite ReadyToRun 會編譯一組必須一起散發的元件。 此優點是編譯器能夠執行更好的優化,並減少無法透過 ReadyToRun 程式編譯的方法集合。 不過,由於取捨,編譯速度會大幅減少,而且應用程式的整體檔案大小會大幅增加。 由於這些取捨,建議只針對停用在 Linux 上執行的 階層式編譯 的應用程式,使用 Composite ReadyToRun,以尋求 獨立 式部署的最佳啟動時間。 若要啟用複合 ReadyToRun 編譯,請指定 <PublishReadyToRunComposite> 屬性。

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

注意

在 .NET 6 中,僅支援獨立式部署 Composite 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