/Ob
控制函数内联的编译器选项。使用 /Ob1
时,仅内联标记为 inline
、__inline
或在类声明中定义的函数,而使用 /Ob2
时,编译器认为合适的所有函数都会内联。
我可以想象一些项目对图像大小有非常严格的限制,使用
/Ob1
而不是 /Ob2
。令人惊讶的是,我们发现一个项目对图像大小没有严格的限制,但却使用了 /Ob1
,而且我们找不到任何这样做的原因。
为什么对可执行文件大小没有严格限制的项目会更喜欢
/Ob1
而不是 /Ob2
?
因为更多的内联会导致代码变大,从而导致缓存利用率降低。由于现代 CPU 会进行积极的分支预测,因此跳入/跳出函数的成本并不一定很高。
缓存的大小有限,因此通过内联代码强制 CPU 放弃缓存中可能存在的其他内容,从而增加未命中次数,从而导致 CPU 停顿。
/Ob1
的选择可能根本就不是选择,而是一种疏忽。现在看到 /Ob1
标志的主要原因是因为它是 CMake 对于 RelWithDebInfo 构建的默认设置。这可能会导致 RelWithDebInfo 和 Release 版本之间存在重大性能差异。我认为这是 CMake 中的一个陷阱,应该将 RelWithDebInfo 更改为默认使用 /Ob2
。
就速度而言,没有真正的原因。内联有一定的权衡,但编译器的启发式几乎肯定比用户更聪明。
我在 64 位发布版本中遇到了 /Ob2 的编译器错误。 使用 /Ob1 可以使问题消失。 项目的开发者可能也遇到过相同或类似的问题。