在Visual Studio中,“优化代码”选项实际上是做什么的?


77

该选项的名称说明了什么,但是Visual Studio /编译器实际上是做什么的,其实际结果是什么?

编辑:如果您搜索谷歌,您可以找到此地址,但这并不是我真正想要的。我不知道真实的事情正在发生。例如,为什么循环会减少时间,等等。

Answers:


63

如果不进行优化,则编译器将生成非常笨拙的代码-每个命令都以非常直接的方式进行编译,从而可以执行预期的操作。调试版本默认情况下禁用优化功能,因为如果不进行优化,则生成的可执行文件将直接与源代码匹配。

变量保存在寄存器中

启用优化后,编译器将应用许多不同的技术来使代码运行更快,同时仍在执行相同的操作。在Visual C ++中,优化和未优化版本之间最明显的区别是,变量值在优化版本中会尽可能长地保存在寄存器中,而没有优化时,变量值总是存储在内存中。这不仅影响代码速度,而且影响调试。这种优化的结果是,调试器在逐步浏览代码时无法可靠地获取变量值。

其他优化

/ O选项(优化代码)MSDN docs中所述,编译器还进行了其他多种优化。有关各种优化技术的一般说明,请参见Wikipedia编译器优化文章


您知道“优化代码”选项如何影响StackTrace类吗?在这个问题stackoverflow.com/questions/628565/…中,coxymla建议取消选中它,但是我没有这样做,它仍然有效。你知道为什么吗 谢谢!
卡洛(Carlo)2010年

1
@Carlo:内联时,您无法在堆栈跟踪中看到内联函数,因为它们根本不存在于代码中(这就是内联的全部内容)。
Suma 2010年

17

来自Paul Vick的博客:

  • 它删除了我们可能会发出的任何NOP指令,以帮助进行调试。当关闭优化(并且打开调试信息)时,编译器将为没有任何实际IL关联但您可能希望在其中添加断点的行发出NOP指令。最常见的示例是“ If”语句的“ End If”-End If没有发出实际的IL,因此我们不会发出NOP调试器不会让您设置断点在上面。启用优化将强制编译器不发出NOP。

  • 我们对生成的IL进行简单的基本块分析,以删除所有无效代码块。也就是说,我们将每种方法分成由分支指令分隔的IL块。通过对块之间的相互关系进行快速分析,我们可以确定没有分支的任何块。因此,我们可以找出永远不会执行且可以省略的代码块,从而使程序集变得更小。此时,我们还进行了一些次要的分支优化-例如,如果您使用GoTo另一个GoTo语句,我们只是优化第一个GoTo以跳转到第二个GoTo的目标。

  • 我们发出一个将IsJITOptimizerDisabled设置为False的DebuggableAttribute。基本上,这允许运行时JIT对代码进行优化以使其适合,包括重新排序和内联代码。这将产生更高效,更小巧的代码,但这意味着尝试调试代码可能会非常具有挑战性(尝试过的任何人都会告诉您)。JIT优化的实际清单是我不知道的-也许像Chris Brumme这样的人会在某些时候加入。总之,优化开关启用了优化功能,这些优化功能可能会使设置断点和单步执行代码变得更加困难。


2

简短的答案是:使用-Ox并让编译器执行其工作。

长话大说:各种优化的效果无法准确预测。有时,针对快速代码进行优化实际上会比针对大小进行优化时产生的代码更小。如果您真的想获得最后0.01%的性能(速度或尺寸),则必须对选项的不同组合进行基准测试。

此外,Visual Studio的最新版本还提供用于更高级的优化的选项,例如链接时间优化和配置文件引导的优化。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.