Share via


JIT 最佳化和偵錯

若您想偵錯程式碼,當該程式碼 不是 最佳化時,會比較容易。 最佳化程式碼時,編譯器和執行時間會變更所發出的 CPU 程式碼,使其執行得更快,但與原始原始程式碼的對應會較不直接。 如果對應較不直接,偵錯工具通常無法告訴您區域變數的值,而且程式碼逐步執行和中斷點可能無法如預期般運作。

注意

如需 JIT (Just In Time) 偵錯的詳細資訊,請參閱 這個文件

.NET 中最佳化的運作方式

發行組建設定通常會建立最佳化的程式碼,而偵錯組建設定則不會。 Optimize MSBuild 屬性會控制編譯器是否被告知要最佳化程式碼。

在 .NET 生態系統中,程式碼會在兩個步驟的流程中從來源轉換成 CPU 指示: 首先,C# 編譯器會將您輸入的文字轉換成稱為 MSIL 的中繼二進位格式,並將 MSIL 寫入 .DLL 檔案。 然後,.NET 執行階段會將此 MSIL 轉換為 CPU 指示。 這兩個步驟都可以最佳化到某種程度,但 .NET 執行階段所執行的第二個步驟會執行更顯著的最佳化。

[在模組負載上隱藏 JIT 最佳化 (僅限受控)] 選項

偵錯工具會公開一個選項,控制當啟用最佳化編譯的 DLL 在目標流程內載入時會發生什麼情況。 如果未核取此選項 (預設狀態),則當 .NET 執行階段將 MSIL 程式碼編譯為 CPU 程式碼時,它會保持最佳化的啟用狀態。 如果已核取此選項,偵錯工具會要求停用最佳化。

若要尋找 [在模組載入上隱藏 JIT 最佳化 (僅限受控)] 選項,請選取 [工具]>[選項],然後選取 [偵錯] 節點底下的 [一般] 頁面。

隱藏 JIT 最佳化

何時應該檢查 [隱藏 JIT 優化] 選項?

當您從另一個來源下載 DLL 時,請檢查此選項,例如 nuget 套件,且您會想偵錯此 DLL 中的程式碼。 若要讓隱藏運作,您也必須找到此 DLL 的符號 (.pdb) 檔案。

如果您只想在本機建置的程式碼進行偵錯,最好不要核取此選項,因為在某些情況下,啟用此選項會大幅降低偵錯速度。 偵錯速度降低的原因有兩個:

  • 最佳化程式碼的執行速度較快。 如果您要關閉許多程式碼的最佳化,效能影響可能會疊加。
  • 如果您已啟用 Just My Code,偵錯工具甚至不會嘗試載入已最佳化的 DLL 符號。 尋找符號可能需要很長的時間。

[隱藏 JIT 最佳化] 選項的限制

在兩種情況下,開啟此選項將 沒有 用:

  1. 在將偵錯工具附加至已在執行的流程的情況下,此選項不會影響附加偵錯工具時已載入的模組。

  2. 此選項不會影響已預先編譯 (或產生) 為機器碼的 DLL。 不過,您可以啟動將環境變數 'COMPlus_ReadyToRun' 設定為 '0' 的流程來停用預先編譯程式碼的使用。 這會告訴 .NET Core 執行階段停用使用預先編譯的映像,強制執行階段使用 JIT 編譯架構程式碼。

    如果您要以 .NET Framework 為目標,請新增環境變數 'COMPlus_ZapDisable',並將它設定為 '1'

將它新增至 Properties\launchSettings.json檔案中的每個設定檔,以設定"COMPlus_ReadyToRun": "0":

{
  "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"
    }
  }
}