为什么在 Visual C++ 9 中更喜欢 /Ob1 而不是 /Ob2,而可执行文件大小没有严格的限制?
Why prefer /Ob1 over /Ob2 in Visual C++ 9 when there're no tight limitations on executable size?
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使问题消失。项目的开发人员可能遇到过相同或类似的问题。
- 在第一种情况下,编译时间可能会稍微快一些。
- 编译器可能并不总是对哪些函数应该使用做出最好的决定内联。内联更多使单个函数更快,可能会使整个程序运行更慢,由于副作用,如缓存溢出。
相关文章:
- 相同的源代码,不同的可执行文件大小?
- 如何在 Linux 中从 .so 文件打开可执行文件?
- 在 Linux 上没有 /proc/self/exe 的 C/C++ 运行时可执行文件的大小?
- 为多个测试文件构建可执行文件
- 我有一个预处理的 C/C++ 源文件 (cacti.i).如何从这个 .i 文件生成可执行二进制文件,以便我可以像 ./
- 仅针对特定可执行文件增加堆栈大小
- 为什么?在改变构建结构后,可执行文件的大小显著减少
- #include 多个.cpp中的标准文件,与将其 #include 在预编译标头中会影响可执行文件的大小?
- 使用.dll文件编译可执行文件,.dll与.exe相关的文件
- 链接后的最小可执行文件大小
- 为什么使用VS 2012构建的MFC对话框的可执行文件大小几乎是使用VS 2005构建的对话框的3倍
- 在gtest中,如何添加库文件到可执行的测试文件
- 使用def文件从可执行文件导出函数
- 以跨平台的方式在c++中调用外部文件(例如可执行文件)
- 创建一个调用另一个可执行文件的可执行文件
- 如何在自定义shell中检测脚本文件与可执行文件
- 如何在 Visual Studio 2010 中生成不依赖于 .NET 4 SDK DLL/库文件的可执行文件?
- 使用g++在不同文件夹中使用.o文件创建可执行文件时出现问题
- 将资源文件嵌入可执行文件的性能
- 如何制作不依赖于 .so 文件的可执行二进制文件