2012-02-06 81 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。

相關問題