2011-05-26 49 views
12

我想知道你的代碼中有沒有使用的函數的開銷是多少。在未使用的代碼中的開銷

例如說你有一些調試日誌記錄,然後給你的大部分對象一個正在調試日誌中使用的ToString()函數。

在未使用調試日誌記錄的發行版本中。那麼值得去除這些ToString()函數的源代碼嗎? (例如,通過宏?)

或者他們只是使可執行文件略微大一點,否則不影響性能?例如沒有速度影響?或者編譯器或鏈接器可能甚至刪除不使用的功能?如果編譯器或鏈接器不刪除代碼,如果ToString()函數是內聯定義的呢?推測它會嘗試內聯代碼,並且由於函數從未被調用,它會消失?

我想每個函數都需要保留在一個靜態庫中,但是一旦編譯成可執行文件,肯定會有很多東西被鏈接器忽略?

在另一個大致相似的註釋中,如果編譯器選擇不內聯內聯函數,以便內聯函數在多個編譯單元中定義爲函數,鏈接器是否會將多餘的定義查找出來並僅鏈接他們在最後?

謝謝

+1

它可能取決於編譯器以及它使用哪些優化。 – soandos 2011-05-26 11:12:49

+4

「不成熟的優化是萬惡之源」 - Donald Knuth – 2011-05-26 11:19:42

+9

我厭倦了過早優化的口頭禪。是的,謝謝你的幫助。另外:「瞭解你在做什麼可能會幫助你做好。」或者你不同意?對編譯器和鏈接器的理解肯定不錯。但感謝您的意見。 – Cookie 2011-05-26 11:26:16

回答

5

它取決於編譯器,我猜,優化級別。

G ++和MSVC++刪除未使用的內聯函數,但保留未使用的非內聯函數。例如,在正常程序中只使用STL的一小部分。所有未使用的函數都被刪除,因爲它們被定義爲內聯。

GCC另一方面保留所有功能,即使未使用的內聯。

回答你的另一個問題:如果一個函數以某種方式在多個編譯單元中定義,鏈接器將皺眉並拒絕鏈接,除非它被定義爲內聯。

+0

只需重新輸入您的最後一句話:除非它被定義爲內聯。這應該可以阻止你的編譯器皺眉,即使它沒有被內聯定義也會皺眉。 – Cookie 2011-05-26 11:29:42

+0

@Cookie:更正,謝謝。 – 2011-05-26 11:32:44

2

鏈接器會刪除重複的功能,並刪除未引用的數據(Microsoft鏈接器提供了/OPF:REF/OPT:ICF開關來調整這些設置)。

你當然是對的,在大多數情況下,連接器是否能夠很好地放棄不需要的或冗餘的東西並不重要 - 對於一些小函數對可執行文件大小的影響(與如果大量使用STL或其他模板庫,則生成的代碼量很小)。

也就是說,如果你需要你的可執行文件,以儘可能小(或者,如果你發現你的調試代碼真的花費大部分的圖像尺寸),#ifdef荷蘭國際集團的一切是執行某些功能的最簡單方法不包括在內。它使得代碼有點難讀,但它的優點是你不會在你的發佈版本中意外地錯過幾處調試代碼,因爲任何試圖調用一個不存在的函數都會導致編譯器錯誤。

#ifdef另一個優點是,它是便攜式的,並且不依賴特定的編譯器系統上: -/

+0

然後你會說最好將這樣的調試tostring函數定義爲內聯嗎? – Cookie 2011-05-26 11:34:21

+2

由於編譯器總是可以內聯或不內聯函數,所以我傾向於使用'inline'僅用於一個目的:能夠在共享頭文件中具有函數定義。由於這對於在類體中定義的成員函數是隱含的,所以我不會指定'inline'。但請注意,這只是我個人的'內聯'方法。 – 2011-05-26 11:36:07

3

1。關於編譯器和鏈接器

這真的取決於你如何創建你的可執行文件。

典型的可執行文件被剝離了任何未被使用的東西。因此,如果您靜態鏈接(並使用正確的優化選項),則該功能將被刪除。

但是,如果您動態鏈接,它們將在那裏,因爲就圖書館而言,它們會被導出並因此被使用。

至於多重定義,它取決於符號是否弱。如果它很弱,那麼鏈接器會選擇其中一個定義,否則會扼殺它。

最後,它們可能只代表您的程序的邊際部分。

2.如何解決該問題?

這是一個很難的問題,你總是可以使用預處理器去除一些東西,但是那些散佈着預處理器指令的代碼真的很煩人。

就我個人而言,我不會打擾...特別是因爲我也在登錄發佈(如何跟蹤生產問題?)。

解決方案可能是在單獨的文件中定義違規函數,而不是在Release中將它們鏈接起來。 注:我不認爲它爲虛函數,因爲它們至少在虛函數表

0

使用。如果你在圖書館一個單獨的文件放置非虛函數,並 鏈接靜態,它應該只有在使用 時纔會添加到可執行文件中。但唯一真正的區別將在於可執行文件的大小,這可能會影響到地區,從而影響業績,但如果它在實踐中真正實現差異化 ,我會感到非常驚訝。所以一般來說,我會說這種技術不值得在應用程序中使用 。 (如果您提供的是第三方庫,另一方面您需要 ,但您絕對需要單獨的文件中的每個非虛函數。)