【问题标题】:Does compiling with -g, in itself, degrade performance? [duplicate]使用 -g 编译本身会降低性能吗? [复制]
【发布时间】:2017-01-06 10:56:08
【问题描述】:

(这是一个关于 gcc 和 clang 的问题,但可能适用于其他编译器。)

如果我编译我的 C 或 C++ 代码,并使用 -g 开关生成调试信息,这本身是否会以任何方式降低已编译程序的性能...

  1. 最小优化 (-O0)?
  2. 最大优化 (-O3)?

注意:我并不是说必须解析/加载可执行文件的性能损失,由于额外的内容,性能损失更大;我的意思是运行的代码。

【问题讨论】:

  • 比较使用-g 编译的程序和没有-g 编译的相同程序。您应该看到实际生成的代码没有区别。
  • @JoachimPileborg:我看不到为特定程序生成的代码的差异这一事实并不一定意味着没有任何差异......
  • 严格来说:是的,至少当您将调试符号保留在可执行文件中时,因为这意味着要加载更多内容(或在加载过程中跳过)。不过,这在 IMO 实践中可以忽略不计。
  • @DanielJour:是的,好吧,公平点,但这不是我的意思。添加注释以澄清。
  • 据我所知,-O3 会降低调试信息的价值,而不是相反。

标签: c++ c gcc clang debug-information


【解决方案1】:

我认为没有任何性能差异。事实上,根据文档here,生成的代码将是相同的,-g 可与-O 一起使用。此外,调试符号不会写入代码中,而是写入另一个称为“调试部分”的部分,它甚至不会在运行时加载(仅由调试器加载)

-g 不会更改运行的优化或生成的代码。 这是here

所述的 gcc 政策

但是,请注意相同的文档指出:

优化代码所采用的捷径有时可能会令人惊讶: 您声明的某些变量可能根本不存在;控制流可能 短暂地移动到你没想到的地方;有些陈述可能不是 执行,因为它们计算常量结果或它们的值是 已经到手了;有些语句可能在不同的地方执行 因为它们已被移出循环。尽管如此还是有可能的 调试优化的输出。这使得使用 可能存在错误的程序的优化器。

因此,最终调试永远不会影响您的优化,但相反是错误的,使用-O3 可能会降低您的调试信息(例如通过删除无用的变量)。

请注意,在这种情况下使用-Og(如here 所述)可能会更好,因为它会:

优化调试体验。 -Og 启用优化 干扰调试。应该是优化级别 标准编辑-编译-调试周期的选择,提供了一个 合理的优化水平,同时保持快速编译 以及良好的调试体验。

但是这会影响性能,因为不会执行一些会干扰调试的优化过程。


编辑:

链接和引号回答了您对gcc 的问题。它可能不适用于其他编译器,例如clang。 不过,我也为clang 找到了一些文档。 比如here:

基本上,调试信息允许你编译一个程序 “-O0 -g”,获取完整的调试信息,让你任意 在从调试器执行时修改程序。编译程序 使用“-O3 -g”可以为您提供始终如一的完整调试信息 可用且准确的阅读(例如,您获得准确的堆栈 尽管尾调用消除和内联的痕迹),但你可能会输 修改程序和调用函数的能力 在程序之外进行优化,或者完全内联。

【讨论】:

  • @einpoklum 这只是一个提醒。但我想开头回答了你的问题。这只是您可能知道的附加信息,但其他人可能不知道。我看到你删除了你的cmets,有什么原因吗?我想我确实在这里回答了你的问题
【解决方案2】:

-g 标志将调试信息添加到二进制文件。这存在于来自.text CPU 运行位的可执行文件的单独部分(.stab.stabstr)中。在调试器之外运行时,操作系统加载程序不会加载调试部分。也可以使用strip 实用程序轻松删除调试信息,以生成与未使用 -g 标志编译的二进制文件相同的二进制文件。

但是,通常当您想要调试内容时,您将在没有优化和 NDEBUG 预处理器宏的情况下进行编译。然而,这些东西不受 -g 标志的控制。

【讨论】:

    【解决方案3】:

    如果您在调试器之外运行它,不会对性能造成任何影响。调试符号是为了帮助调试。在这两种情况下生成的代码应该是相同的。

    【讨论】:

    • 发表一些东西来支持你的观点。
    猜你喜欢
    • 2018-12-12
    • 1970-01-01
    • 1970-01-01
    • 2011-04-26
    • 1970-01-01
    • 2015-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多