Visual Studio 2013 年优化标志(/O2 vs /Ox)
Visual Studio 2013 optimization flags (/O2 vs /Ox)
我一直在尝试阅读 MSDN pages 中关于各种优化标志的内容。
我们目前的大部分项目都设置为 /O2
,这针对 "maximize speed" 进行了优化。
我的困惑是这到底是什么意思。关于 /O2
标志,以下哪些陈述更接近于正确?
- 优化速度和大小的代码,但如果有争用更喜欢速度优化
- 优化代码仅速度,不优化大小。
我提出了我们应该使用 /Ox
标志的论点,但当时我认为选项 2 是正确的。
我基本上是被告知 "we're not going to change from /O2
to /Ox
unless someone has solid evidence that we need to do so"。
所以我的问题是 /O2
是否仍然执行内存优化?例如。 return 值优化、复制省略等。从 /O2
切换到 /Ox
我们会得到什么?
So my question is does /O2 still perform memory optimizations?
取决于您所说的内存优化是什么意思。
/O1 保证根据二进制大小优化代码。
Creates the smallest code in the majority of cases.
/O2 主要旨在优化代码以获得更快的速度。
Creates the fastest code in the majority of cases. (default setting
for release builds)
当
时/O2与/O1正交的情况(不限)
- 编译器会展开循环,
- 代码重新排序
- 代码内联
现在考虑 /Ox,它生成的代码有利于执行速度而不是较小的大小,因此 /Ox 不包括 /Os(有利于小代码)通过指示编译器最小化 EXE 和 DLL 的大小大小胜于速度。
/02
等同于 /Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy
/Ox
等同于 /Og /Oi /Ot /Oy /Ob2
所以从 /O2
切换到 /Ox
意味着:
- 无
/Gs
(无控件堆栈探测)
- 无
/GF
(无字符串池)
- 无
/Gy
(无函数级链接)
正如 Arkanosis 正确指出的那样,当 从 /O2 转到 /Ox 时,您禁用 /Gs、/GF、/Gy。问题是 这些标志中的哪些可以提高执行速度?
/Gs 与 /Gs0 相同, 会对性能产生负面影响。请参阅下面 MSDN 上的说明。
activates stack probes for every function call that requires storage
for local variables. This can have a negative impact on performance
/GF 消除重复字符串(常量)——称为字符串池化。这将减少代码大小。较低的代码可能会产生较少的指令缓存未命中数,但我怀疑这种效果在大多数代码上都能观察到。
/Gy 标志允许将单个函数打包到 COMDAT 结构中。这些可以用作解决方法,以避免由于同一符号的多个定义而导致编译时错误。 MSDN 文档指出这只会影响构建时间而不影响执行时间。他们通常推荐使用它。
结论:
/Ox 禁用 /Gs、/GF、/Gy。在某些情况下,与 /O2 相比,这些选项会损害性能并且几乎不会提高执行速度。当然他们有好处,但与速度无关。
我一直在尝试阅读 MSDN pages 中关于各种优化标志的内容。
我们目前的大部分项目都设置为 /O2
,这针对 "maximize speed" 进行了优化。
我的困惑是这到底是什么意思。关于 /O2
标志,以下哪些陈述更接近于正确?
- 优化速度和大小的代码,但如果有争用更喜欢速度优化
- 优化代码仅速度,不优化大小。
我提出了我们应该使用 /Ox
标志的论点,但当时我认为选项 2 是正确的。
我基本上是被告知 "we're not going to change from /O2
to /Ox
unless someone has solid evidence that we need to do so"。
所以我的问题是 /O2
是否仍然执行内存优化?例如。 return 值优化、复制省略等。从 /O2
切换到 /Ox
我们会得到什么?
So my question is does /O2 still perform memory optimizations?
取决于您所说的内存优化是什么意思。
/O1 保证根据二进制大小优化代码。
Creates the smallest code in the majority of cases.
/O2 主要旨在优化代码以获得更快的速度。
Creates the fastest code in the majority of cases. (default setting for release builds)
当
时/O2与/O1正交的情况(不限)- 编译器会展开循环,
- 代码重新排序
- 代码内联
现在考虑 /Ox,它生成的代码有利于执行速度而不是较小的大小,因此 /Ox 不包括 /Os(有利于小代码)通过指示编译器最小化 EXE 和 DLL 的大小大小胜于速度。
/02
等同于/Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy
/Ox
等同于/Og /Oi /Ot /Oy /Ob2
所以从 /O2
切换到 /Ox
意味着:
- 无
/Gs
(无控件堆栈探测) - 无
/GF
(无字符串池) - 无
/Gy
(无函数级链接)
正如 Arkanosis 正确指出的那样,当 从 /O2 转到 /Ox 时,您禁用 /Gs、/GF、/Gy。问题是 这些标志中的哪些可以提高执行速度?
/Gs 与 /Gs0 相同, 会对性能产生负面影响。请参阅下面 MSDN 上的说明。
activates stack probes for every function call that requires storage for local variables. This can have a negative impact on performance
/GF 消除重复字符串(常量)——称为字符串池化。这将减少代码大小。较低的代码可能会产生较少的指令缓存未命中数,但我怀疑这种效果在大多数代码上都能观察到。
/Gy 标志允许将单个函数打包到 COMDAT 结构中。这些可以用作解决方法,以避免由于同一符号的多个定义而导致编译时错误。 MSDN 文档指出这只会影响构建时间而不影响执行时间。他们通常推荐使用它。
结论:
/Ox 禁用 /Gs、/GF、/Gy。在某些情况下,与 /O2 相比,这些选项会损害性能并且几乎不会提高执行速度。当然他们有好处,但与速度无关。