Share via


ReadyToRun コンパイル

アプリケーション アセンブリを ReadyToRun (R2R) 形式としてコンパイルすることにより、.NET アプリケーションの起動時間と待機時間を向上させることができます。 R2R とは、Ahead-Of-Time (AOT) コンパイルの一種です。

R2R バイナリでは、アプリケーションの読み込み時に Just-In-Time (JIT) コンパイラで行う必要がある作業量を減らすことにより、起動時のパフォーマンスが向上します。 バイナリには、JIT で生成されるものと似たネイティブ コードが含まれます。 ただし、R2R バイナリは、中間言語 (IL) コード (一部のシナリオでまだ必要です) と同じコードのネイティブ バージョンの両方が含まれるため、大きくなります。 R2R は、Linux x64 や Windows x64 などの特定のランタイム環境 (RID) を対象とするアプリを発行するときにのみ使用できます。

プロジェクトを ReadyToRun としてコンパイルするには、PublishReadyToRun プロパティを true に設定してアプリケーションを発行する必要があります。

アプリを ReadyToRun として発行するには、次の 2 つの方法があります。

  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 機能を使用した場合の影響

Ahead Of Time コンパイルには、アプリケーションのパフォーマンスに対して複雑な影響があり、その予測は困難な場合があります。 一般に、アセンブリのサイズは 2 から 3 倍の大きさになります。 このようにファイルの物理サイズが大きくなると、ディスクからのアセンブリの読み込みのパフォーマンスが低下し、プロセスの作業セットが大きくなる可能性があります。 ただし、代わりに、実行時にコンパイルされるメソッドの数は一般に大幅に減少します。 その結果、大量のコードを使用するほとんどのアプリケーションでは、ReadyToRun を有効にすることにより、パフォーマンスに関して大きなメリットがあります。 ReadyToRun によって .NET ランタイム ライブラリが既にプリコンパイルされているため、コードの量が少ないアプリケーションでは、ReadyToRun を有効にしてもそれほど向上しない場合があります。

ここで説明する起動に関する向上は、アプリケーションの起動時だけでなく、アプリケーションで何かのコードを初めて使用するときにも当てはまります。 たとえば、ReadyToRun を使用すると、ASP.NET アプリケーションで Web API を初めて使用するときの応答待機時間を短縮できます。

階層型コンパイルとの相互作用

Ahead Of Time で生成されるコードは、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>

これらのシンボルは publish ディレクトリに配置され、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