2012-10-14 11 views
12

私には大きな問題があります。私は共通のライブラリを持っています。それは私のプロジェクト全体で使用されています。このライブラリは集中的にboost.spiritboost.fusionを使用しています。残念ながら、ライブラリは約です。 700Mbのサイズ。すべてのboost.spirit - 重いコードが使用され、うまく動作します。出力サイズを減らすためにはどのようなステップを実行できますか?テンプレートインスタンシエーションが大部分のスペースを無駄にしているかどうかを判断するのに役立つツールはありますか?テンプレート重い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バイトのブロブとして扱うことができるので、もう一方に委譲することができ、ただ正しい型にキャストバックする物のラッパーとして機能するので、ベクトルの内部構造をある型に対してのみインスタンス化し、 2つではなく。

  • 別のコンパイラを試してみてください。コンパイラの中には、プログラムのセマンティクスに影響を及ぼさない同一のテンプレートインスタンシエーションを再利用するものもあれば、より保守的なものもあります。

  • ライブラリからエクスポートされたものを注意してください。エクスポートされず、内部的に参照されないシンボルは、リンカによって削除できます。 (もちろん、静的ライブラリをビルドしている場合は、実行可能ファイルにリンクされていない限り、ライブラリのサイズを縮小することはできません)

しかし最終的には、テンプレートの重いライブラリを使用する必要があるかもしれません。 (またはあなたが現在持っているよりも簡単パーサを書く)

+1

テンプレートインスタンス化を再利用する際の問題の1つは、通常、各関数は異なるアドレスを持つ必要があり、実行可能コードが異なる場合でも異なる関数を一緒に適切に融合させないことです。 VC++がそれほど気にしないと思いますが、この最適化はコンパイラがアドレスがプログラム内で使われていないことを証明できる場合にのみ利用できます。 –

+0

@MatthieuM。それはすべてのコンパイラがそれをするわけではありません。一般的には非常に安全な最適化です(関数のアドレスを頻繁に比較することはしませんが、そうしたときにはほとんどの場合、無効であると思われます)。しかし、コンパイラがそれを検出するのはかなり簡単です。テンプレート重いコードの実行可能なサイズの不思議 – jalf

4

--ffunction-sections ...同じ関数本体を融合するためのフラグを覚えているようだが、再び見つけることができないようです。それ自体では有効ではありませんが、リンカーは未使用セクションを--gc-sectionsで削除できます。今度は--function-segmentsがなくても、これはソースファイル全体が未使用の場合、つまり非常に細かい場合にのみ機能します。

明らかに、Matthieuが述べた可視性属性が必要です。そうでないと、ライブラリ内のすべての機能が表示されるため「使用」されます。

関連する問題