在Visual Studio中,"优化代码"选项实际上是做什么的?
时间:2020-03-06 14:31:48 来源:igfitidea点击:
该选项的名称说明了什么,但是Visual Studio /编译器实际上是做什么的,其实际结果是什么?
编辑:如果我们搜索谷歌,我们可以找到此地址,但这并不是我真正想要的。我不知道真实的事情正在发生。例如,为什么循环会减少时间,等等。
解决方案
简短的答案是:使用-Ox并让编译器完成其工作。
答案很长:不同类型的优化的效果无法准确预测。有时,针对快速代码进行优化实际上会比针对大小进行优化时产生的代码更小。如果我们真的想获得性能的最后0.01%(速度或者大小),则必须对选项的不同组合进行基准测试。
此外,Visual Studio的最新版本还提供了用于更高级优化的选项,例如链接时间优化和配置文件引导的优化。
如果不进行优化,则编译器会生成非常笨拙的代码,每个命令都将以非常直接的方式进行编译,从而可以执行预期的操作。调试版本默认情况下禁用优化,因为如果不进行优化,则生成的可执行文件将直接与源代码匹配。
变量保存在寄存器中
启用优化后,编译器将应用许多不同的技术来使代码运行得更快,同时仍保持相同的状态。在Visual C ++中,优化和未优化的版本之间最明显的区别是,变量值在优化的版本中会尽可能长地保存在寄存器中,而没有优化的变量值总是存储在内存中。这不仅影响代码速度,而且影响调试。这种优化的结果是,调试器无法在逐步执行代码时可靠地获取变量值。
其他优化
如/ O选项(优化代码)MSDN文档中所述,编译器还应用了其他多项优化。有关各种优化技术的一般说明,请参见Wikipedia编译器优化文章。
从保罗·维克(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这样的人会在某个时候加入。总而言之,优化开关启用了优化功能,这些优化功能可能会使设置断点和逐步遍历代码变得更加困难。