2012-02-06 76 views
4

我看到一些代码,是这样的只有调用另一个函数的函数会减慢速度吗?

int *func2(int *var) { 
    //Do some actual work 
    return var; 
} 

int *func1(int *var) { 
    return func2(var); 
} 

int main() { 
    int var; 
    var = func1(&var); 
    return 0; 
} 

这似乎是一个令人难以置信的浪费给我,但我想通了中间功能以前可能有两个功能,它可以致电或有一些扩展计划未来。我只是想知道像gcc这样的编译器是否可以检测到这种事情,并消除实际程序中的无用功能,或者如果这种事实际上在运行时会浪费CPU周期?

+1

你问关于gcc具体还是一个理论问题 - 编译器能做到吗? – amit 2012-02-06 23:42:35

+0

是的,我在Mac和一些Linux机器上使用gcc。但我总的来说很好奇,因为我真的很新奇,想知道是否为了保持低水平而做大量的功能是个好主意。 – chinakow 2012-02-07 02:29:47

回答

1

超级快速回答:可以。

快速回答:是的,但通常不够,你应该照顾,有时根本不会。

完整的答案:如果函数都是在同一个翻译单元,编译器不吸,函数调用额外的一层只会得到优化掉了,而且会有性能影响。否则,如果您正在进行外部函数调用,则需要一个小但非零的性能成本。大多数情况下,这并不重要,但是对于每个周期都是超短的函数,它可能会使程序慢两倍,甚至更糟。一些最坏情况下的例子:

  1. getc的函数,仅仅从一个缓冲器拉的下一个字节,前进的位置,并返回(在通常情况下,其中所述缓冲液是非空)。
  2. 一种通过平凡的操作推进状态机并返回的函数,例如处理单个字节的UTF-8字符。
  3. 锁定/同步原语。这有点特殊,因为实际的原子内存访问应该支配执行时间,使得开销看起来不重要。但是,如果您的预期用例只是为了容纳一个简单的操作(例如lock(); a++; unlock();),那么如果锁被高度争用,那么即使锁定时间较少,也会对争用性能产生严重影响。

最后,你应该做的答案是:尽可能以最自然的方式编写代码,直到测试/测量显示出现性能问题。只有这样你才应该考虑为了性能而忽略你的代码。

4

在大多数情况下,如果您将编译器优化设置得足够高,这些微不足道的函数将会是inlined。因此没有开销。

所以你的问题的答案是:是的,编译器通常足够聪明,以消除呼叫。
所以不要担心它,除非你需要。

您也可以使用关键字inline使其更明确:(尽管编译器仍然可以自由地忽略它)

inline int *func1(int *var) { 
    return func2(var); 
} 
12

不要做过早的优化。专注于编写可读代码。即使没有优化,额外的函数调用可能对性能影响最小。编译器可以选择内联它。

如果您以后遇到性能问题,可以通过测试和配置文件查找瓶颈。

0

这取决于编译器和运行时环境。如果方法调用位于堆栈上,则会增加堆栈的额外开销。但是在这种情况下,所有事情都是通过指针来完成的,所以这可能是尾部调用,并且可能会被内联。内联/尾调用将导致函数类似于跳转而不是堆栈递增操作;这意味着它将在运行时类似于循环或goto。

相关问题