JIT の最適化とデバッグ

コードをデバッグしようとする場合、コードが最適化されていない方が簡単です。 コードを最適化すると、コンパイラとランタイムにより、出力された CPU コードをより高速に実行できるように変更が行われますが、元のソース コードへのマッピングはあまり直接的ではありません。 マッピングがあまり直接的でないと、多くの場合に、デバッガーはローカル変数の値を示すことができず、コードのステップ実行やブレークポイントが期待どおりに機能しない可能性があります。

Note

JIT (ジャストインタイム) デバッグの詳細については、こちらのドキュメントをお読みください。

.NET での最適化のしくみ

通常、リリース ビルド構成では最適化されたコードが作成されますが、デバッグ ビルド構成ではそれが作成されません。 Optimize MSBuild プロパティを使用して、コンパイラにコードを最適化するよう指示するかどうかを制御します。

.NET エコシステムでは、コードが 2 段階のプロセスでソースから CPU 命令に変換されます。最初に、入力したテキストが C# コンパイラによって MSIL という中間バイナリ形式に変換され、MSIL が .dll ファイルに書き込まれます。 その後、.NET ランタイムによって、この MSIL が CPU 命令に変換されます。 どちらのステップでもある程度最適化できますが、.NET ランタイムによって実行される 2 番目のステップでは、より大幅な最適化が行われます。

[モジュールの読み込み中に JIT 最適化を抑制する (マネージドのみ)] オプション

最適化を有効にしてコンパイルされた DLL がターゲット プロセス内で読み込まれたときの動作を制御するオプションがデバッガーによって公開されます。 このオプションがオフ (既定の状態) の場合、.NET ランタイムによって MSIL コードが CPU コードにコンパイルされると、最適化は有効なままになります。 このオプションをオンにすると、デバッガーによって最適化を無効にするように要求されます。

[モジュールの読み込み時に JIT 最適化を抑制する (マネージのみ)] オプションを見つけるには、 [ツール]>[オプション] を選択し、 [デバッグ] ノードの下にある [全般] ページを選択します。

JIT 最適化の抑制

[JIT 最適化を抑制する] オプションをオンにする必要があるケース

このオプションは、nuget パッケージなどの別のソースから DLL をダウンロードし、この DLL のコードをデバッグする場合にオンにします。 抑制を機能させるには、この DLL のシンボル (.pdb) ファイルも検索する必要があります。

このオプションを有効にすると、デバッグが大幅に遅くなる場合があるので、ローカルでビルドしているコードのデバッグにのみ関心がある場合は、このオプションをオフのままにすることをお勧めします。 この低速化には、次の 2 つの理由があります。

  • 最適化されたコードの方が高速に実行されます。 多くのコードの最適化をオフにすると、パフォーマンスへの影響が大きくなる可能性があります。
  • [マイ コードのみ] が有効になっている場合、デバッガーは最適化された DLL のシンボルの読み込みさえも試行しません。 シンボルの検索には長時間かかることがあります。

[JIT 最適化を抑制する] オプションの制限

このオプションをオンにすると機能しない状況が 2 つあります。

  1. 既に実行中のプロセスにデバッガーをアタッチする場合、このオプションは、デバッガーがアタッチされた時点で既に読み込まれていたモジュールには影響しません。

  2. このオプションは、ネイティブ コードに対してプリコンパイル済み (ngen 済み) の DLL には影響しません。 ただし、環境変数 'COMPlus_ReadyToRun''0' に設定してプロセスを開始することで、プリコンパイル済みコードの使用を無効にすることができます。 これにより、.NET Core ランタイムに、プリコンパイル済みイメージの使用を無効にし、ランタイムに JIT コンパイル フレームワーク コードを強制するように指示します。

    .NET Framework を対象としている場合は、環境変数 'COMPlus_ZapDisable' を追加し、それを '1' に設定します。

"COMPlus_ReadyToRun": "0" を設定するには、Properties\launchSettings.json ファイル内の各プロファイルにそれを追加します。

{
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:59694/",
      "sslPort": 44320
    }
  },
  "profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "COMPlus_ReadyToRun": "0"
      }
    },
    "HttpLoggingSample": {
      "commandName": "Project",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "COMPlus_ReadyToRun": "0"
      },
      "applicationUrl": "https://localhost:5001;http://localhost:5000"
    }
  }
}