-
Notifications
You must be signed in to change notification settings - Fork 0
MS_ReadyToRunAndTieredCompilation
段階コンパイル
- JIT の最適化を段階的に行い、パフォーマンスを改善する仕組み。
- 一部のシナリオではプリコンパイル済みのコードより速くなる。
補足(なぜ「段階」なのか): JIT には根本的なトレードオフがある。
起動速度 定常性能 最適化なしで即コンパイル 速い 遅い 最適化ありでコンパイル 遅い 速い どちらか一方を選ぶと他方が犠牲になる。
そこで「まず速くコンパイルして動かし、
よく呼ばれるものだけ後から最適化し直す」という折衷にしたのが
Tiered Compilation である。1 回しか呼ばれないメソッドに最適化コストを払わない、
という点が本質的な効きどころになる。
コンパイル時に Tier 0 なネイティブコードも同時に生成する仕組み。
Tier 0 なネイティブコードを実行時に Tier 1 へ差し替える仕組み。
コンパイルの段階
- 初めて呼ばれるメソッドは一律「最適化なし」で JIT コンパイル
- 使用頻度の高いメソッドは実行環境へ最適化されたコードへの差し替えが出来る。
- 呼ばれた回数をカウントして、一定数を越えたら「最適化あり」で JIT コンパイル
- 実行中でも戻り先アドレスに補正をかけるので、実行中に JIT コンパイル可能
移行メモ: 元ページは「オン中でも」「オン中に」と表記されていたが、
文意から「実行中」(メソッドがスタック上にある状態)と解釈して改めた。
技術的には **OSR(On-Stack Replacement)**と呼ばれる仕組みで、
.NET 7 で既定有効になった。これにより
「長いループを 1 回だけ回すメソッド」も途中で Tier 1 に差し替えられる。
補足(R2R と AOT の違い): 名前が紛らわしいので整理しておく。
方式 実体 JIT 特徴 JIT のみ IL のみ配布 必要 起動が遅い ReadyToRun (R2R) IL + プリコンパイル済みネイティブ 必要(Tier 1 で使う) 起動が速い。サイズは増える Native AOT ネイティブのみ 不要 最速起動・最小メモリ。リフレクション等に制約 R2R は「IL を捨てない」のが要点で、
起動時は事前生成コードを使い、ホットパスだけ実行環境に合わせて
再 JIT する(= AOT の起動速度と JIT の最適化を両取りする)。<PublishReadyToRun>true</PublishReadyToRun>なお 初回が遅い! で扱われる
「初回リクエストが遅い」問題に対して、R2R は有効な打ち手になる。
補足(既定値): 現在の .NET では
- Tiered Compilation は既定で有効(.NET Core 3.0 以降)
- Tiered PGO(プロファイルに基づく最適化)は .NET 8 で既定有効
- R2R は発行時に明示的に指定する(既定は無効)
ベンチマークを取る際は、Tier 1 に上がるまでウォームアップすること。
ウォームアップ無しの計測は Tier 0 の性能を見ているだけになりやすい
(BenchmarkDotNet はこれを自動で行う)。
-
段階コンパイル (Tiered Compilation) | ++C++; // 未確認飛行 C ブログ
https://ufcpp.net/blog/2018/12/tieredcompilation/ -
.NET Core 3.0 で有効化される Tiered Compilation と ReadyToRun について - しばやん雑記
https://blog.shibayan.jp/entry/20190912/1568291738 -
ReadyToRun 展開 | Microsoft Learn
https://learn.microsoft.com/dotnet/core/deploying/ready-to-run -
階層型コンパイル | Microsoft Learn
https://learn.microsoft.com/dotnet/core/runtime-config/compilation
Tags: 移行, .NET開発, .NET Core
このWikiは「Open棟梁Project」,「OSSコンソーシアム 開発基盤部会」によって運営されています。