“禁用托管优化并重启调试”在 Visual Studio 中实际更改了哪些设置?

What settings does "Disable managed optimizations and restart debugging" actually change in Visual Studio?

提问人:Jez 提问时间:4/19/2023 最后编辑:Jez 更新时间:4/21/2023 访问量:934

问:

在 Visual Studio 2022 调试会话期间,我正在使用源链接和Microsoft符号服务器调试一些 ASP.NET 内部代码,但我无法查看变量,因为它已被优化;但是,概览有一个“禁用托管优化并重新开始调试”选项。我选择了它,调试重新启动,我确实能够查看变量。但是,我现在担心我已经禁用了一些优化,这可能会减慢速度,而且我不清楚选择该选项实际上改变了什么。在 Visual Studio 中更改了哪些设置,如何重新启用托管优化?

下面是该选项在 UI 下拉列表中的外观以及单击它时的外观的一些屏幕截图:

Dropdown

Upon click

asp.net 调试 visual-studio-2022

评论

0赞 Bowman Zhu-MSFT 4/20/2023
请您分享一些关于您提到的“概览有一个”禁用托管优化并重新启动调试“选项的屏幕截图?
0赞 Jez 4/20/2023
麻烦的是,现在我已经禁用了它们,该选项不再出现。:-)
0赞 Jez 4/20/2023
好的,我设法让它再次出现在另一个调试会话中,并且我添加了屏幕截图。
0赞 Dai 4/20/2023
“我已经禁用了一些优化,这可能会减慢速度”——是的,但这不是问题:调试版本并不意味着快速。
0赞 Jez 4/20/2023
@Dai那么,为什么它首先要优化它呢?

答:

-1赞 Albert D. Kallal 4/20/2023 #1

让优化未开启将简单地“不”编译代码以运行得更快(作为编译的机器代码)。因此,您可以单步执行并查看代码变量。但是,在调试具有大量代码的大型应用程序时,未缩影的代码将运行得相当慢。因此,您可以选择允许代码更快地运行,但调试过程 THEN 无法使用或查看变量的值,因为该代码的调试信息不存在。如果代码已缩减,那么在大多数情况下,这意味着它已编译为机器代码,调试器实际上无法显示变量的值,甚至不允许断点。

从某种意义上说,如果你允许优化,那么你运行的代码就像它以“发布模式”运行一样,因此选项和你调试此类代码的能力会大大降低。

如今,计算机具有如此巨大的速度和处理能力,那么我几乎可以接受,在几乎所有情况下,您都希望在禁用优化的情况下调试代码。

评论

0赞 Dai 4/20/2023
OP 询问的是调试器设置中的 JIT 优化器设置,而不是一般的优化。
0赞 Albert D. Kallal 4/21/2023
是的,在这种情况下,这正是我要说的。该优化代码实际上是由 JIT 编译并且也经过优化的代码。正如我所说,如果您禁用该选项,则可以单步执行并使用断点。所以,是的,我的整个响应是关于编译器(或者在这种情况下是 JIT)的。那么,现在你已经掌握了我的背景是什么?您可以在给定的上下文中再次阅读我的帖子,因此我相信您 100% 同意我所说的。
0赞 Dai 4/21/2023
“如果你允许优化,那么你运行的代码就像它以”发布模式“运行一样,因此选项和你调试此类代码的能力会大大降低。- 这是真的,但同时没有提到这是如何工作的 W.R.T.Just-My-Code 模式以及 Modules 窗口和 .COMPlus_ZapDisable
4赞 Dai 4/21/2023 #2

Background-info:.NET 中不同类型的优化

在许多编译语言(如 C 和 C++)中,通常只有一个地方应用优化:当您运行编译器时(尽管具有单独的编译器和链接器的旧工具链通常具有单独的编译时和链接时优化)。

...但在 .NET 世界中,它稍微复杂一些:

  • C#-to-IL(或 VB.NET-to-IL、F# 等)编译器可以优化从 C# 生成的 IL(/optimize 标志)。csc

    • 这些往往是更简单的优化,例如删除死代码(例如,块的内容,如 )。if( false ) { /* here */ }
  • 当 CLR 加载生成的 .NET 程序集(.NET 或 )时,JIT 可以应用自己的优化。.dll.exe

    • 这些往往更高级,例如循环展开和可执行代码内联。
    • 这些 JIT 时间优化不适用于具有或带有 - 将 csc.exe/debug 一起使用时,此属性将添加到程序集中。DebuggableAttribute( DebuggingModes.DisableOptimizations )isJITOptimizerDisabled: false
  • 虽然严格来说不是编译器“优化”,但当 .NET 程序运行时,CLR 可能会加载特定于计算机的托管程序集的缓存本机映像版本

    • 对于 .NET Framework 1.x-4.x 程序集,这些本机映像由 - 生成,它(从 Windows 8 开始可以在后台抢占式编译程序集,而无需手动运行。ngen.exengen.exe
    • 对于 .NET 5+,请参阅 CrossGen2
    • 这与和/或 AOT 编译的程序集不同,后者有自己的优化,超出了此答案的范围。readytorun

推荐阅读


“禁用托管优化并重启调试”在 Visual Studio 中实际更改了哪些设置?

消息框允许您更改“在模块加载时禁止 JIT 优化(仅限托管)”设置,> >:ToolsOptionsDebugging

enter image description here

但是,我现在担心我已经禁用了一些优化,这可能会减慢速度

不用担心:“Suppress JIT optimization...”设置只会在调试时阻止对非项目程序集进行 JIT 优化 - 尽管在许多情况下仍将使用 ngen'd 映像(因此,除非您使用 ),否则仍会运行优化的 cod。COMPlus_ZapDisable

在 Visual Studio 中更改了哪些设置,如何重新启用托管优化?

转到“调试器设置”,然后取消选中“禁止 JIT 优化...”选择。


如果使用“调试器模块”窗口查看加载的每个 .NET 程序集及其 JIT 优化状态、符号状态,以及 VS 是否将其视为“用户代码”,则可以看到发生了什么。

enter image description here

enter image description here