【发布时间】:2024-01-08 20:27:01
【问题描述】:
正如很久以前所建议的,我总是在没有帧指针的情况下构建我的发布可执行文件(如果使用 /Ox 编译,这是默认设置)。
但是,现在我在论文http://research.microsoft.com/apps/pubs/default.aspx?id=81176 中读到,帧指针对性能没有太大影响。因此,完全优化它(使用 /Ox)或使用帧指针完全优化它(使用 /Ox /Oy-)对性能并没有真正的影响。
微软似乎表示添加帧指针 (/Oy-) 会使调试更容易,但真的是这样吗?
我做了一些实验,发现:
- 在一个简单的 32 位测试可执行文件(使用 /Ox /Ob0 编译)中,省略帧指针确实提高了性能(大约 10%)。但是这个测试可执行文件只执行一些函数调用,没有别的。
- 在我自己的应用程序中,添加/删除帧指针似乎没有太大影响。添加帧指针似乎可以使应用程序快 5% 左右,但这可能在误差范围内。
关于帧指针的一般建议是什么?
- 是否应该在发布的可执行文件中省略它们 (/Ox),因为它们确实对性能有积极影响?
- 是否应该将它们添加 (/Ox /Oy-) 到发布的可执行文件中,因为它们可以提高调试能力(使用故障转储文件进行调试时)?
使用 Visual Studio 2010。
【问题讨论】:
-
函数调用是它唯一优化的东西,每次调用只有几个指令。它确实减少了所需的堆栈空间(除非您进行深度递归,否则这无关紧要)
-
如果你知道堆栈指针在哪里,我总觉得帧指针有点多余(对于编译器来说,这很容易)。
-
我假设“10%”的速度优势来自 32 位 x86,它只有 7 个通用寄存器(不包括堆栈指针),因此将其中 1 个用作帧指针是很重要。
-
@PeterCordes 你是对的。过去几年我不再考虑帧指针,因为我们现在都是 64 位的(并且提到的编译器选项在 64 位 Visual Studio 中不存在)。寄存器的数量确实可以在其中发挥重要作用。
-
GCC 在任何模式下都支持
-fno-omit-frame-pointer(对于非 x86 目标)。这是一个众所周知的事实,即 1 个可用寄存器的增量值增加的总数越少,来自 CS 论文已经探索了这一点,例如为各种模拟机器编译 SpecInt 并查看代码大小和动态指令数。但是,在 x86(包括 x86-64)上,帧指针有时可以在经常引用堆栈变量的代码中节省代码大小;[rbp+-disp8]的编码比[rsp +- disp8]小。因此,有时省略 FP 反而会带来伤害而不是帮助。
标签: performance visual-studio-2010 visual-c++ x86 stack-frame