2010-12-08 56 views
6

靜態庫的性能大於動態庫是一個普遍的概念。我的問題是:它是否也取決於一旦dll已經加載到內存中?我的意思是,一旦初始化和所有事情發生,在動態庫的情況下函數調用和執行花費的時間比靜態庫更長?靜態庫與動態庫性能

+0

你在問關於DLL,但你的問題被標記爲`linux`。你的環境究竟是什麼樣子? – Asaph 2010-12-08 06:27:26

+0

你在Linux或Windows上嗎?共享庫和位置獨立代碼系統是非常不同的。 Windows DLL在Linux的意義上並不是獨立的位置,雖然它們可以重新定位 – 2010-12-08 06:36:13

回答

8

免責聲明:我是Linux-fu蚱蜢,所以可能會有一些不準確的地方(或者只是到處)。但總體思路應該是比較正確的。如果不是這樣,我相信那些優秀的人會很快糾正我。 :-)

哦,我提供的鏈接是以Windows爲中心的。如果有人能提供適當的以Linux爲中心的鏈接,我將不勝感激。

簡答:可能。但是,即使這樣做,性能差異也是微不足道的。

當您鏈接靜態庫時,編譯器會生成代碼以直接執行所有函數調用。當進程被創建並且代碼被執行時,函數調用是一個簡單的調用指令。

當你使用一個動態庫,成本取決於您是否使用加載時動態鏈接運行時動態鏈接

load-time dynamic linking,編譯器仍然生成代碼來直接調用該函數,就好像它是一個靜態鏈接。當進程加載器加載DLL時,它將調用運行時鏈接器來修復進程內存,以便這些調用直接進入實際的函數實現。這必須在從加載的庫調用函數之前發生。在Windows上,它由NT DLL加載器完成,它在進程初始化時調用DLL上的LoadLibrary。在Linux上,它由運行時鏈接程序ld-linux.so完成。

隨着/DELAYLOAD加載時動態鏈接,這個過程是esentially相同的,除了編譯器生成的代碼來調用小存根,如果庫被加載,這將檢查,如果沒有,將調用NT DLL加載器。因此,DLL將按需加載,並且進程加載器不必在進程初始化時加載它。這會導致更快的流程啓動時間,但通話性能仍然相同。 (但是請注意,延遲負載有其他缺點)

我不知道是否有相應的Linux支持,但如果沒有,我會感到驚訝。

使用run-time dynamic linking,您的代碼將維護函數指針並決定何時卸載庫。在Windows上,它必須使用LoadLibrary和GetProcAddress,在Linux上它是dlopen,dlsym和dlclose。在任何情況下,對進程啓動時間的影響與對於延遲加載加載時間動態鏈接;然而,每個方法調用的指針取消引用確實會增加一個微不足道的成本。 (雖然如果你知道自己在做什麼,你可能會瘋狂並修復你的進程內存以避免指針取消引用,然而,正確的做法比你獲得的性能好得多它)。

3

我認爲最大的區別,性能明智的是,與靜態庫的編譯器可以優化函數調用到庫,但在動態的一個編譯器不知道它的功能行爲呼叫。

0

DLL或靜態庫中的機器代碼本身具有相同的性能。編譯器可以更積極地使用靜態庫優化可執行文件,特別是在啓用鏈接時代碼生成時。人們可以考慮刪除未使用的變量,並且在一起使用時重複代碼和代碼的放置位置(見PGO)。

當跨應用程序共享代碼時,最好從性能的角度來使用DLL,因爲系統的整體內存壓力較小(當OS能夠映射跨Windows進程的內存部分視圖時一樣)。