2013-09-28 64 views
2

我一直在用Valgrind做一些測試,以瞭解函數如何被編譯器翻譯,並且發現由於沒有被內聯,有時候寫在不同文件上的函數與寫在同一個源文件中的函數相比性能差。爲什麼不將編譯器內聯函數寫入不同的源文件?

考慮到我有不同的文件,每個文件都包含與特定區域相關的函數,並且所有文件都共享一個聲明所有函數的通用頭文件,這是預期的嗎?

爲什麼當編譯器在不同的文件上編寫它們時,編譯器不會內聯它們,而是當它們在同一頁上時內聯?

如果此行爲開始導致性能問題,那麼建議採取的行動方案是什麼?在編譯之前手動將所有功能放在同一文件中?

例如:

//source 1 
    void foo(char *str1, char *str2) 
    { 
     //here goes the code 
    } 

//source 2 
    void *bar(int something, char *somethingElse) 
    { 
     //bar code 
     foo(variableInsideBar, anotherVariableCreatedInsideBar); 
     return variableInsideBar; 
    } 

樣品性能成本:

在不同的文件:29920

二者都在同一個文件:8704

對於更大的功能是不那麼明顯,但仍然發生。

回答

-1

哇,你是怎麼注意到的。我認爲那是因爲你編譯了一些東西,起初編譯器將一個c文件轉換成一個目標文件而不查看任何其他文件。在創建目標文件後,它不會應用任何優化。

我不認爲它花費太多perfomance。

+0

即使在最高級別上進行了優化,它也會發生在頭上聲明的所有函數,並且同時編譯所有函數。 – 2013Asker

+0

然後編譯器將源代碼編譯爲目標文件,他只查找這個c文件,並從頭文件中獲取具有函數聲明的常量。它不知道使用的函數的代碼,他只知道如何調用它們,並且稍後將鏈接器的信息留給鏈接該函數。它不能內聯該代碼,他甚至不知道在這個階段。如果你願意,你可以簡單地複製它。 – user2547526

2

如果您使用的是gcc,則應嘗試選項-combine-fwhole-program,並在一次調用中將所有源文件傳遞給編譯器。傳統上不同的C文件是分開編譯的,但是優化交叉編譯單元(文件)變得更爲常見。

+0

此選項的MS版本爲/ gl 值得注意的是,在大型項目中,這些選項可以完全摧毀迭代時間。我不知道gcc,但是在MS工具鏈中,鏈接是單線程的,所以你最終只需要30分鐘以上的鏈接時間,而無法加快速度。 –

1

編譯器本身不能內聯函數定義在不同的翻譯單元,因爲它看不到這些函數的定義,即它看不到這些函數的源代碼。歷史上,C編譯器(以及該語言本身)圍繞獨立翻譯的原則而構建,其中包括。每個翻譯單元將編譯成從源代碼轉換爲完全獨立於其他翻譯單元的目標代碼。只有在翻譯的最後階段,所有這些不相交的目標代碼片段通過所謂的鏈接器一起組裝成最終程序。但是在當時的傳統編譯器實現中,任何內容都已經太晚了。

正如您可能知道的那樣,函數內聯的語言級支持表示,爲了使某個函數在某些翻譯單元中是「可引用的」,它必須在該翻譯單元中定義,即其主體的源代碼該翻譯單元中的編譯器應該可見。這一要求直接源於上述獨立翻譯原則。

許多現代編譯器正在逐步引入克服經典純獨立翻譯限制的功能。他們實現了諸如全局優化這樣的功能,其允許各種優化穿越翻譯單元的邊界。這可能包括內聯其他翻譯單元中定義的函數的功能。請查閱您的編譯器文檔以查看它是否可以跨翻譯單元內聯函數以及如何啓用此類優化。

這種全局優化默認情況下通常是禁用的原因是它們可以顯着增加翻譯時間。

相關問題