2009-05-14 5 views
13

多くのクラスがあると、クラスごとに1つの* .hと1つの* .cppファイルを使用すると、コンパイル時間が大幅に増加することがわかりました。非として*の.cppファイルに定義cpp翻訳単位の数を減らすのがいいですか?

  • :だから私は、次のトリックを思い付いた

    ;(はい、私はブーストを使用して)私はすでにプリコンパイル済みヘッダーとインクリメンタルリンクを使用していますが、まだコンパイル時間が非常に長いです-compilable

  • 定義された* .CXXファイルをコンパイルとして
  • は、アプリケーション モジュールごとに1 * .CXXファイルを追加して、その中にこのモジュールのすべての*の.cppファイルをインクルード。

だからではなく、私は唯一の8翻訳単位になってしまった100+翻訳単位の。コンパイル時間は4-5倍短くなりました。

すべての* .cppファイルを手動でインクルードする必要があるという欠点があります(ただし、リンカがあなたに思い出させるものを含むのを忘れた場合はメンテナンスの悪夢ではありません)。このスキームでは、例えば

など実装に移動/に行きそこで問題は、本当に唯一の真の方法をCPPの翻訳単位の多くを持っているのですか?私のトリックを知られているパターン、または私は何かが不足している? ありがとう!私はそれがそうでない場合は行うことができなかった最適化を行うだけでなく、多くのメモリを節約するようにコンパイラーに役立ちますので、あなたはビデオゲームで何を見てきた

答えて

4

。私は "uber build"と "bulk build"を見たことがあります。それはあなたのビルドをスピードアップする場合に役立ちますと、このアプローチの理由ではない。..

5

一つの大きな欠点は、各翻訳単位に1つの.objファイルを持つことによって引き起こされます。

他のプロジェクトで再利用するために静的ライブラリを作成すると、多くの小さな翻訳単位ではなく、いくつかの巨大な翻訳単位がある場合、それらのプロジェクトで大きなバイナリに直面することがよくあります。ライブラリを使用してプロジェクト内から実際に参照される変数。

は大きな翻訳単位の場合には、各ユニットが参照されている可能性が高いですし、対応する.objファイルが含まれています。場合によっては、より大きなバイナリが問題になることがあります。リンカの中には、.objファイル全体ではなく、必要な関数や変数だけを含むようにスマートに機能する人もいます。また

の.objファイルが含まれており、すべてのグローバル変数は、プログラムが確実に時間がかかりますどの停止/開始されたときに、あまりにも、その後彼らのコンストラクタ/デストラクタが呼び出されますが含まれている場合。

+0

と呼ばれます。Visual Studioは、機能レベルのリンクをサポートしています。しかし、Unix/Linuxにはまだ関係があります。 – MSalters

+0

機能レベルのリンクは関数または変数だけを除外しますか? – sharptooth

1

より大きい翻訳単位では、並列コンパイルを利用できません。私はあなたが使用しているコンパイラやどのようなプラットフォームを知りませんが、並列複数の翻訳単位でコンパイルすると大幅建物時間が低下する可能性があります...単一のファイルにC++ソースコードファイルの大きな数をバンドル

+0

これは必ずしも真実ではありません.OPはVisual Studioを使用していると言います。最新のバージョンでは、適切なコマンドラインパラメータを追加すると、複数のプロセッサを使用して単一のソースファイルをコンパイルできます。 –

+0

スピードアップが同じであるという保証はありません。単一のソースファイルをコンパイルするために複数のスレッドを使用する方法を知っていることは難しい問題です。複数の別々のコンパイルでビルドを配布できるのと同じくらい効率的ではないでしょうか。 –

3

はアプローチです最近、特に大規模なシステムを構築し、複雑なヘッダーファイルを取得していたとき(これは後押しになるでしょう)に数回言及されています。

あなたがVSと言いましたように、プロジェクト内のインクルードファイルの数、特にインクルードパスのサイズが、g ++のコンパイル時よりもはるかにVisual C++のコンパイル時間に影響するようです。これは、ソースコードで必要とされるすべてのインクルードファイルを見つけるために多数のファイル検索が必要であるため、多くのネストされたインクルード(特に、ブーストはこれを行う)の場合に特に当てはまります。コードを単一のソースファイルにまとめるということは、コンパイラが上記のインクルードを見つけることについてもっと賢くなることを意味します。また、同じサブプロジェクト内のファイルに非常に似ている可能性が高いヘッダーファイルのセット。

C++開発の「たくさんのコンパイル単位」アプローチは、通常、クラスをデカップリングし、クラス間の依存関係を最小限に抑えたいので、変更を加えた場合にコンパイラは最小限のファイルセットを再作成する必要があります。これは一般的には良いアプローチですが、サブプロジェクトでは実際には実行できません。なぜなら、そこにあるファイルには互いに依存関係があるため、大規模な再構築が必要になるからです。

0

sharptoothsの投稿に続いて、結果の実行ファイルをいくつか詳しく調べる傾向があります。それらが異なる場合は、テクニックをビルドをデバッグするのに制限し、メインリリースビルドのオリジナルプロジェクト設定に頼る傾向があります。実行可能ファイルをチェックする際には、起動時と実行中にメモリの使用量とリソースの使用量を調べます。

2

これはあなたのケースでは関係ないのか分かりませんが、代わりに宣言を使用して#includeの数を減らす必要があります。また、同じ目的でpimplイディオムを使用することもできます。これは、毎回再コンパイルする必要があるソースファイルの数と、取り込む必要のあるヘッダの数を減らすことになります。

3

コンパイル単位の数を減らすことは良い考えではありません。大きなコンパイル時間で問題を解決しようとしていますが、このアプローチは助けになるようですが、さらにあなたが得られるもの:

  1. 開発中のコンパイル時間の増加。通常、開発者は一度に少数のファイルを変更します。コンパイルはおそらく3〜4つの小さなファイルの方が速くなり、1つの非常に大きなファイルの場合はコンパイルが速くなります。
  2. あなたが言及したように、コードをナビゲートするのは難しいですが、IMHOこれは非常に重要です。
  3. 1つの.cxxファイルに含まれている.cppファイル間に干渉が生じることがあります。

    a。 cppファイル(デバッグビルド用)のマクロをメモリリークチェックのためにローカルに定義するのが一般的です。残念ながら、これは、プレースメントnew(いくつかのSTLとBOOSTヘッダーのように)を使用してヘッダーを組み込む前に行うことはできません。

    b。 cppファイルに宣言を使用して追加するのが一般的な方法です。あなたのアプローチでは、これは後で含まれるヘッダーに問題を引き起こす可能性があります。

    c。名前の競合は

IMHO、非常にクリーン(多分、より高価な方法)コンパイル時間をスピードアップするためにいくつかの分散ビルドシステムを使用することでより多くの可能性があります。それらはクリーンなビルドに特に効果的です。

関連する問題