为什么在 Visual C++ 9 中更喜欢 /Ob1 而不是 /Ob2,而可执行文件大小没有严格的限制?

Why prefer /Ob1 over /Ob2 in Visual C++ 9 when there're no tight limitations on executable size?

本文关键字:文件大小 可执行 C++ Visual 更喜欢 为什么 Ob1 Ob2      更新时间:2023-10-16

Visual c++的/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使问题消失。项目的开发人员可能遇到过相同或类似的问题。

  1. 在第一种情况下,编译时间可能会稍微快一些。
  2. 编译器可能并不总是对哪些函数应该使用做出最好的决定内联。内联更多使单个函数更快,可能会使整个程序运行更慢,由于副作用,如缓存溢出。