JIT 优化和调试

如果您正在尝试调试代码,那么当代码未优化时,这会更容易。 优化代码时,编译器和运行时会更改发出的 CPU 代码,使其运行速度更快,但直接映射到原始源代码较少。 如果映射不太直接,调试器通常无法告诉你局部变量的值,并且代码单步执行和断点可能无法按预期工作。

注释

有关 JIT(实时)调试的详细信息,请阅读 本文档

优化在 .NET 中的工作原理

通常,发布生成配置会创建优化的代码,调试生成配置不会。 Optimize MSBuild 属性控制编译器是否被告知优化代码。

在 .NET 生态系统中,代码在两步过程中从源转换为 CPU 指令:首先,C# 编译器将键入的文本转换为名为 MSIL 的中间二进制形式,并将 MSIL 输出到 .dll 文件。 稍后,.NET 运行时将此 MSIL 转换为 CPU 指令。 这两个步骤都可以优化到某种程度,但 .NET 运行时执行的第二个步骤会执行更显著的优化。

“取消模块加载上的 JIT 优化(仅限托管)”选项

调试器公开一个选项,用于控制在目标进程内启用优化编译的 DLL 时会发生什么情况。 如果未选中此选项(默认状态),则当 .NET 运行时将 MSIL 代码编译为 CPU 代码时,它将保持启用优化。 如果选中了此选项,调试器将请求禁用优化。

若要在模块加载(仅限托管)选项上查找“禁止 JIT 优化”选项,请选择“工具>选项”,然后选择“调试”节点下的“常规”页。

禁止 JIT 优化

何时应检查“取消 JIT 优化”选项?

如果您从其他渠道(如 nuget 包)下载了 DLL,并且希望调试 DLL 中的代码,请选中此选项。 为了使抑制功能正常工作,同时需要查找此 DLL 的符号 .pdb 文件。

如果只对在本地生成的代码感兴趣,最好将此选项保留为未选中状态,因为在某些情况下,启用此选项会显著降低调试速度。 这有两个原因导致速度变慢:

  • 优化的代码运行速度更快。 如果要关闭大量代码的优化,性能影响可能会增加。
  • 如果已启用“仅我的代码”,调试器甚至不会尝试加载已优化的 DLL 的符号。 查找符号可能需要很长时间。

“禁止 JIT 优化”选项的限制

在以下两种情况下,启用此选项将 不起作用

  1. 在将调试器附加到正在运行的进程的情况下,此选项对附加调试器时已加载的模块没有影响。

  2. 此选项对已预编译(或使用 ngen 编译)到本机代码的 DLL 没有影响。 但是,可以通过将环境变量“COMPlus_ReadyToRun”设置为“0”启动进程来禁用预编译代码的使用。 这会告知 .NET Core 运行时禁用预编译映像的使用,迫使运行时执行 JIT 编译框架代码。

    如果要面向 .NET Framework,请添加环境变量 “COMPlus_ZapDisable” 并将其设置为 “1”。

"COMPlus_ReadyToRun": "0" 添加到 属性\launchSettings.js上的 文件中的每个配置文件,以进行设置:

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