【问题标题】:Effect of removal "static" keyword for function删除函数的“静态”关键字的效果
【发布时间】:2017-04-03 09:03:36
【问题描述】:

最近了解到“backtrace”函数的存在。 该函数允许在某些情况下检索没有调试信息编译的 ELF 运行程序的调用堆栈。

这对我来说是完美的(我不能在生产程序中插入调试符号),但是要让“回溯”工作,(大致)有两个条件:

  • 告诉链接器添加额外信息(通过传递 -rdynamic 选项)。
  • 将所有“静态”函数转换为“非静态”函数。

我担心的是,如果我满足这两个条件,我的程序会变慢(因为编译器不能像优化静态函数一样优化非静态函数?)。 据我所知,使用 -rdynamic 添加额外信息不会影响程序的性能:它只是给 ELF 二进制文件增加了一点权重。

这是我的问题:

当所有静态函数都变成非静态函数时,对运行性能有什么影响?

【问题讨论】:

  • 'static' 只影响范围/可见性,不是吗?
  • 我忘了写下来,但据我所知,是的,静态影响范围/可见性。我怀疑的地方是“静态”是否只影响范围/可见性。我认识的人说这也可能影响编译器优化,但他无法用源代码支持他所说的话,他也不确定。如果因为编译器需要计算额外的步骤来进行相同的优化而在编译时出现停机时间,那么它不会打扰我。但如果运行时出现停机,则值得考虑。
  • 这与 C 或 C++ 有关吗?可能相关:stackoverflow.com/questions/572547/… 如果我没记错的话,C 中的static 只能用于变量,不能用于函数; statc 函数是什么意思?
  • 它仅用于 [c]。静态函数是仅在声明该函数的 .c 文件中可见的函数。

标签: c


【解决方案1】:

是的,您的担心是正确的:将函数声明为 static 为编译器提供了一个很好的提示,它可以转化为更好的优化。不过,您从 static 获得的加速量取决于您的具体情况,因此只有衡量标准才是正确的(在性能方面总是如此)。

将函数声明为static 的要点在于,编译器明确知道,它可以看到所有函数的调用位置。如果它发现该函数只从一个地方调用,它通常总是内联它,不管它有多长。内联可能会释放更多的优化机会。这在大小和速度方面都避免了函数调用开销。在这方面,static 实际上是比inline 更强的提示。

当然,对性能的影响取决于调用static 函数的频率。因此,正如我所说,您需要通过测量来评估您从 static 关键字中获得了多少性能。

【讨论】:

  • 但是外部函数也可以在它们的翻译单元中内联。与static 的唯一区别在于,对于 extern 函数,编译器总是必须生成一个非内联体,而对于静态函数,该体可能不是必需的(如果所有调用都是内联的)。但是当涉及到从同一个翻译单元发出的调用时,static 不会“解锁”任何额外的内联机会。在该翻译单元内部,静态函数和外部函数的这些机会完全相同。
  • @AnT 这个额外的非内联副本正是问题所在:它占用了空间。当您有足够大的函数并将其声明为inline 时,编译器很可能会决定忽略您的提示,因为添加第二个副本的成本太大。 (这是一个启发式决策,将内联的成本与不内联的成本进行权衡。)当编译器发现根本不需要第二个副本时,内联的成本正好为零,允许内联的函数不会被内联没有static 关键字的内联。并且内联解锁了进一步的优化。
【解决方案2】:

当所有静态函数都变成非静态函数时,对运行性能有什么影响?

我认为答案是“一些”。您可以确定性能问题可能是什么的唯一方法是测量使用和不使用静态函数的程序的性能。我能想到的最明显的事情是优化器可能无法内联非静态函数。

您实际上不需要将静态函数设为非静态函数,唯一的问题是回溯中缺少符号名称。

但是,我认为你有更大的问题。从您到手册页的链接:

帧指针的省略(正如 gcc(1) 的任何非零优化级别所暗示的那样)可能会导致违反这些假设。

为了使backstrace 可靠地工作,看起来您必须在没有优化的情况下进行编译。这肯定会对性能产生巨大影响。我想没有它我也能应付。

【讨论】:

  • 那条小线第一次逃过我...我想我会留下所有静态关键字和所有 gcc 的优化,如果碰巧我有一个适当的调用堆栈,那么我会很高兴。谢谢。
  • 用优化的代码进行调试无论如何都是误导和痛苦的。
【解决方案3】:

当所有静态函数都变成非静态函数时,对运行性能有什么影响?

回答 - 无

静态函数意味着该函数仅对该文件可见,并且不能在该文件之外调用。即它具有文件范围

当您不希望自己的函数与其他人的函数发生冲突时,通常在大型程序中使用静态函数。静态函数确保您可以定义一个函数并在自己的文件中使用它,其他人也可以在其他文件中定义相同的静态函数名称。

如果您的代码在删除 static 关键字后编译,那么您没有两个同名的函数,它将像任何普通函数一样工作。

它不会有运行时间损失。

【讨论】:

  • 这不是真的。 static 使编译器的函数 inling 变得更加容易,这可能会影响性能。是否可以检测到差异,取决于用例。
猜你喜欢
  • 2011-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多