2012-10-14 101 views
12

我有一個很大的問題。我有一個共同的圖書館,用於我的項目。該庫密集使用boost.spiritboost.fusion。不幸的是,圖書館是約。 700Mb的大小。所有的boost.spirit -heavy代碼被使用,它運作良好。可以採取哪些措施來減少產量?是否有一種工具可以幫助確定哪些模板實例會浪費大部分空間?如何減少模板沉重的C++代碼的輸出大小?

起初,我決定將所有精神感知代碼移動到cpp文件。其次,我將嘗試使用不同的編譯器標誌來優化大小。我不知道還有什麼要做。

更新(詳細信息)

我使用的GNU工具鏈。巨大的庫實際上是一個靜態庫。使用700Mb庫的可執行文件大小爲200Mb。至少一半的代碼位於* .h文件中。一些boost.spirit語法(很模板很重的東西)也位於* .h文件中。

乾杯!

回答

5

移動精神感知代碼到.cpp文件是一個很好的第一步,它可能是不完整的,雖然你提到在頭文件中有精神語法。

  1. 請確保沒有任何語法/規則導出到庫之外。如果您有典型的include/src目錄,則將這些文件(即使標頭)移動到src目錄中。

  2. 標記所有這些符號作爲內部圖書館。他們不應該從圖書館外進出。根據你的編譯器有特定的編譯指示/屬性,在gcc查找visibility attribute__attribute__ ((visibility ("internal")))。這有助於編譯器相應地優化它們,特別是編譯器可能會發出函數的代碼,即使它在給定的調用站點內聯了它,以防發生該函數地址。但是,使用內部可見性,因爲它知道代碼不會離開對象,所以可能會使函數失效。

  3. 我似乎記得一個標誌,融合功能相同的身體,但似乎無法再次找到......

+0

感謝「visibility」屬性,不知道它。 – Lazin

2

幾點建議:

  • 如果可能的話,儘量重複使用相同的模板實例(如一個簡單的,和做作,例如,std::vector<int>std::vector<float>將具有相同的內部結構,既可以只把不透明的4個字節的二進制大對象的元數據,使人們可以委託給其他的,只是充當一個東西包裝剛剛投下回到正確的類型,從而使載體的內部只需要實例化一個類型,而不是兩個。

  • 嘗試不同的編譯器。一些編譯器在不會影響程序語義的情況下重複使用相同的模板實例,而其他編譯器則更保守。

  • 密切關注從圖書館輸出的內容。未導出且未在內部引用的符號可通過鏈接器刪除。 (當然,如果你正在構建一個靜態庫,這將不會直到它被鏈接到可執行一命嗚呼爲了降低庫本身的大小,你可以嘗試使其成爲一個動態庫,而不是)

但最終,這聽起來像你可能只需要使用較少的模板庫。 (或寫一個簡單的解析器比你目前有)

+1

重複使用模板實例化的一個問題是,通常每個函數都應該有不同的地址,並且即使它們的可執行代碼不同,也會阻止將不同功能融合在一起。我不認爲VC++對此非常關心,但是嚴格意義上的這種優化只有在編譯器可以證明程序中沒有使用地址時纔可用... –

+0

@MatthieuM。真的,這就是爲什麼並非所有編譯器都這麼做的原因。它通常是一個非常安全的優化(你不經常比較函數地址,當你這樣做時,我懷疑在大多數情況下它是無效的,編譯器檢測它是相當簡單的) - 然而,它確實奇妙的模板大小代碼的可執行文件大小 – jalf

4

--ffunction-sections將會把每個功能在自己的段。本身沒有用,但鏈接器可以用--gc-sections刪除未使用的部分。現在沒有--function-segments,這隻有在整個源文件未被使用,即具有瘋狂的粒度的情況下才有效。

很明顯,您需要Matthieu提到的可見性屬性,否則庫中的所有函數都會因爲可見而「使用」。