使用 -g gcc 标志编译的程序是不是比不使用 -g 编译的同一程序慢?
Posted
技术标签:
【中文标题】使用 -g gcc 标志编译的程序是不是比不使用 -g 编译的同一程序慢?【英文标题】:Is a program compiled with -g gcc flag slower than the same program compiled without -g?使用 -g gcc 标志编译的程序是否比不使用 -g 编译的同一程序慢? 【发布时间】:2014-07-29 19:17:09 【问题描述】:我正在编译一个程序,使用 -O3 来提高性能,使用 -g 来调试符号(如果发生崩溃,我可以使用核心转储)。一件事让我很困扰, -g 选项会导致性能下降吗?当我查看带和不带 -g 的编译输出时,我发现不带 -g 的输出比带 -g 的编译输出小 80%。如果额外的空间用于调试符号,我不关心它(我猜),因为这部分在运行时不使用。但是,如果对于没有 -g 的编译输出中的每条指令,我需要在使用 -g 的编译输出中多执行 4 条指令,而不是我当然更愿意停止使用 -g 选项,即使以无法处理核心转储为代价。
如何知道程序中调试符号部分的大小,通常使用 -g 编译会创建一个运行速度比不使用 -g 编译的相同代码慢的程序?
【问题讨论】:
你对它进行了基准测试吗? 对这个程序进行基准测试并不容易,真的,如果容易做到我不会问这个问题,我会自己衡量惩罚。 我已经测量过了。看来他们的运行速度相同。-g
只是添加了调试符号。显然这取决于你的程序。
MSVC 使用单独的pdb file 来存储调试符号,您甚至可以在发布模式下进行调试,因此有时您甚至会面临一个已优化且其值未定义的变量。不知道gcc有没有类似的选项
【参考方案1】:
引用自gcc documentation
GCC 允许您将-g 与-O 一起使用。优化所采取的捷径 代码有时可能会产生令人惊讶的结果:一些变量你 声明的可能根本不存在;控制流可能会短暂地移动到哪里 你没想到;有些语句可能无法执行,因为 他们计算出恒定的结果,或者他们的值已经在手; 有些语句可能在不同的地方执行,因为它们已经 移出循环。
意思是:
我会为你插入调试符号,但如果优化通过将它们搞砸,我不会尝试保留它们,你必须处理它
调试符号不会写入代码,而是写入另一个称为“调试部分”的部分,该部分甚至不会在运行时加载(仅由调试器加载)。这意味着:没有代码更改。您不应该注意到代码执行速度的任何性能差异,但是如果加载器需要处理较大的二进制文件或者如果它以某种方式考虑到增加的二进制文件大小,您可能会遇到一些缓慢。您可能必须自己对应用程序进行基准测试,才能在特定情况下 100% 确定。
请注意,gcc 4.8 中还有 another option:
-Og
优化调试体验。
-Og
启用不干扰调试的优化。它应该是标准编辑-编译-调试周期的首选优化级别,提供合理的优化级别,同时保持快速编译和良好的调试体验。
此标志将影响性能,因为它将禁用任何会干扰调试信息的优化通道。
最后,可能甚至会发生某些优化更适合特定架构而不是另一种架构的情况,除非针对您的特定处理器进行了指示(请参阅您的架构的 march/mtune 选项) , 在 O3 中,gcc 将为通用架构尽其所能。这意味着在某些人为的场景中,您甚至可能会遇到 O3 比 O2 慢的情况。 “尽力而为”并不总是意味着“最好的”。
【讨论】:
FWIW 你甚至可以指定如何实现这一点,即march
和mtune
。
请注意,即使您注意到由于-g
导致的性能差异,您也可以使用objcopy --strip-debug
和objcopy --only-keep-debug
将调试信息移动到单独的文件中。以上是关于使用 -g gcc 标志编译的程序是不是比不使用 -g 编译的同一程序慢?的主要内容,如果未能解决你的问题,请参考以下文章