gccとmakeファイルを使用するプロジェクトがあります。プロジェクトには、1つの大きなサブプロジェクト(SDK)と、そのSDKといくつかの共有フレームワークを使用する比較的小さなサブプロジェクトが多数含まれています。GCC /ビルド時間の最適化
プリコンパイルされたヘッダーを使用しますが、再コンパイルのみが高速になるのに役立ちます。
ビルド時の最適化に役立つ既知の手法とツールはありますか?あるいは、これや関連するトピックに関するいくつかの記事/リソースを知っているかもしれませんか?
gccとmakeファイルを使用するプロジェクトがあります。プロジェクトには、1つの大きなサブプロジェクト(SDK)と、そのSDKといくつかの共有フレームワークを使用する比較的小さなサブプロジェクトが多数含まれています。GCC /ビルド時間の最適化
プリコンパイルされたヘッダーを使用しますが、再コンパイルのみが高速になるのに役立ちます。
ビルド時の最適化に役立つ既知の手法とツールはありますか?あるいは、これや関連するトピックに関するいくつかの記事/リソースを知っているかもしれませんか?
問題を2つの側面から取り除くことができます。コンパイラーが見ている複雑さを軽減するコードをリファクタリングするか、コンパイラーの実行をスピードアップします。
コードに触れることなく、コンパイルのパワーを追加できます。 ccacheを使用して、すでにコンパイルしたファイルを再コンパイルしないようにし、distccを使用して複数のマシンにビルド時間を配布します。 make -jを使用します。ここで、Nはコア数、ローカルでコンパイルする場合は+1、分散ビルドの場合はより大きい数です。このフラグは複数のコンパイラを並列に実行します。
コードをリファクタリングします。包含宣言を含むことが好ましい(単純)。依存性を避けるためにできるだけデカップリングしてください(PIMPLイディオムを使用してください)。
テンプレートインスタンシエーションは高価で、それらを使用するすべてのコンパイル単位で再コンパイルされます。テンプレートをリファクタリングして前方に宣言してから、1つのコンパイル単位でインスタンス化することができる場合は、
私はmake
と考えることができる最高は-j
オプションです。これは、並行して、できるだけ多くのジョブを実行するためにmake
に指示します:
make -j
あなたはnに同時実行ジョブの数を制限したい場合あなたが使用することができます。
make -j
N
依存関係が正しいことを確認しますのでmake
それはDOEジョブを実行しません。そんなことはありません。
考慮すべきもう一つは、gcc
が-O
スイッチで行い最適化です。さまざまなレベルの最適化を指定できます。最適化が高くなればなるほど、コンパイルとリンク時間は長くなります。私が実行しているプロジェクトは、-O3
とリンクするのに2分、そして-O1
で半分かかります。必要以上に最適化していないことを確認する必要があります。開発ビルドの最適化と展開ビルドの最適化なしでビルドできます。デバッグ情報(gcc -g
)でコンパイル
は、おそらくあなたの実行可能ファイルのサイズが大きくなりますし、ビルド時間に影響を与える可能性があります。あなたがそれを必要としない場合は、それがあなたに影響を与えるかどうかを確認するためにそれを削除してみてください。
リンクのタイプ(静的か動的か)は違いがあります。私が知っている限り、静的リンクにはもっと時間がかかります(私はここで間違っているかもしれませんが)。これがビルドに影響するかどうかを確認する必要があります。
あなたが開発者のマシンでLANを持っている場合は、おそらくあなたは、このようなdistccとして、分散型コンパイラのソリューションを実装してみてください。
ビルド中の時間のすべての依存関係を分析する費やし、またはいくつかの単一のシリアルタスクを行っている場合、これは助けない可能性があります。多くのソースファイルをオブジェクトファイルにコンパイルする際には、Nathanが示唆するように、並列ビルドが明らかに役立ちます(単一のマシン上で)。複数のマシン間でパラレル化すると、それをさらに活用できます。
http://ccache.samba.org/は、時間を大幅に短縮します。
私は中型のプロジェクトで作業し、それは我々が、コンパイル時間をスピードアップするために行うだけのことです。
__DATE __/__ TIME__または関連するマクロで愚かな手品をしない限り、ccacheは繰り返しクリーンビルドを高速化するのに適しています。一方、きれいなビルドを頻繁にやっているのであれば、あなたの再構築システムが壊れていることを意味し、最初に修正する必要があります... – ephemient
プロジェクトの説明から、ディレクトリごとに1つのMakefileがあり、再帰的なmakeをたくさん使っていると思います。その場合、"Recursive Make Considered Harmful"からの技術は大いに役立つはずです。
また、ソースコードファイルをできるだけ小さく/自在に保つこと、つまり1つの巨大な単一オブジェクトファイルよりも多くの小さなオブジェクトファイルを好むことをお勧めします。
これは、不必要な再コンパイルを避けるのにも役立ちます。さらに、ソースコードディレクトリまたはモジュールごとにオブジェクトファイルを持つ静的ライブラリを1つ持つことができます。
これまでの回答では言及されていなかったことは、シンボルリンケージを可能な限り「プライベート」なものにしています。つまり、コードに静的なリンケージ(関数、変数)外部から見える。
また、ELFターゲット用のC++コードをコンパイルする場合はであるGNU gold linkerを調べることもできます。
基本的に、ビルドプロセスを慎重にプロファイルし、最も多くの時間が費やされている場所を確認することをお勧めします。ビルドプロセスやプロジェクトのソースコード構造を最適化する方法についてのヒントがあります。
複数のマシンにアクセスできる場合は、distcc分散コンパイラを使用してビルド時間を短縮することができます。 は、ここではdistccに関連するIBMのdeveloperWorksからの記事だと、あなたはそれを使用する方法: http://www.ibm.com/developerworks/linux/library/l-distcc.html
ビルド時間を短縮する別の方法は、プリコンパイル済みヘッダーを使用することです。ここにはstarting point for gccがあります。
また、マシンに複数のCPU /コアがある場合は、-jを使用してビルドするときに-jを使用することを忘れないでください(コア/ CPUの数は2倍です)。
SConsなど、別のビルドシステムに切り替えることを検討できます(誰にも当てはまりません)。 SConsはmakeよりはるかにスマートです。自動的にヘッダー依存関係をスキャンするので、常に最小限の再構築依存関係が保持されます。あなたのSConstructファイルにラインDecider('MD5-timestamp')
を追加することで、SConsは最初にファイルのタイムスタンプを見て、以前にビルドされたタイムスタンプよりも新しい場合は、ファイルのMD5を使って実際に何かを変更したことを確認します。これは、ソースファイルだけでなくオブジェクトファイルでも機能します。つまり、たとえばコメントを変更した場合、再リンクする必要はありません。
ヘッダーファイルの自動スキャンによって、scons --cleanと入力する必要がなくなります。常に正しいことをします。
小さいファイルを使用することは常に推奨するとは限りません。ディスクは32または64K分のセクタサイズを持ち、ファイルは少なくとも1セクタを占めます。したがって、3Kサイズ(内部の小さなコード)の1024ファイルは、予想される3メガバイトではなく、実際にディスク上で32または64メガバイトを取ることになります。ドライブで読み取る必要がある32/64メガファイルがディスクの周りに分散していると、シーク時間によって読み取り時間がさらに長くなります。これは明らかにディスクキャッシュの限界に役立ちます。あらかじめコンパイルされたヘッダーもこれを緩和するのに役立ちます。
したがって、コーディングガイドラインを尊重して、各strcuct、typedef、またはユーティリティクラスを別々のファイルに配置するだけでは意味がありません。
make -jが実際に動作するように再帰が行われていることも確認してください。たとえば、 "make -C subdir"を呼び出すことなく、$(MAKE)などを使用します。 – richq
私はその提案を理解しているかどうか分かりません。 –
あなたのmakefileがちょうどmakeを呼び出して再帰する場合、トップレベルのmakeだけが-j argを使用するので、-jでスケーラビリティを得ることはできません。$(MAKE)を使用する必要があります。あなたはすべての仕事を走らせる良い機会になります。 –