遅いコンパイル環境でコーディングするための最善の方法は何ですか


15

私はC#でTDDスタイルのコーディングを使用していました。小さなコードの塊を作成/変更し、ソリューション全体を10秒で再コンパイルし、テストを再実行します。簡単...

その開発方法論は、私が数年間、C ++コーディングに戻らなければならなかった昨年まで非常にうまく機能し、それ以来、私の生産性は劇的に低下したと感じています。言語としてのC ++は問題ではありません-私はC ++開発の経験がかなりありました...しかし、過去には。

私の生産性は小さなプロジェクトでも大丈夫ですが、プロジェクトのサイズが大きくなり、コンパイル時間が10分以上になると悪化します。そして、エラーを見つけた場合は、コンパイルを再開する必要があります。それは純粋にイライラさせられます。

したがって、私は小さなチャンク(以前のように)は受け入れられないと結論付けました-コードを手動でレビューするときに(高速C#コンパイラに依存せずに)1時間ほどコーディングの古い習慣にどのように身を置くことができますか? 、数時間に1回だけユニットテストを再コンパイル/再実行します。

C#とTDDでは、進化的な方法でコードを書くのは非常に簡単でした-数十回の繰り返しの後、私が始めたがらくたは良いコードになりましたが、それはもううまくいきません(遅いコンパイルで)環境)。


stackoverflow.com/questions/5078409 / ...これらはおそらく1か所に統合​​する必要があります。
ベンL

C ++コンパイル時間の高速化については、lasostackoverflow.com/questions/373142/ を参照してください。
Eclipseの


前回コンパイル済みヘッダーを使用してC ++を本格的に使用したとき、コンパイル時間を4分の1に短縮しました。
gnasher729

回答:


16

いくつかのことが思い浮かびます。

  1. 分散コンパイルを利用します。これは、GCC( "distCC"?)またはVC(XoreaxのIncrediBuildは正確に安くはありませんが、それに費やすすべての価値があります。)でこれを行うことができます。

  2. プロジェクトを動的にロードされるライブラリに分割し、それらへの依存関係を最小限に抑えてください。より小さい実行可能ファイルは、はるかに高速にリンクします。

  3. 大きなアプリケーション全体ではなく、小さなテストプロジェクトに対してプログラムします。

  4. コンパイル時にアルゴリズム実行するには、テンプレートメタプログラミングを使用します。はい、これは実際にコンパイル時間を増加させますが、テストに必要なターンアラウンドも減少させます:それがうまくコンパイルすれば、完了です。

  5. ハードウェアに投資します。より多くのCPUカーネル(お使いのマシンまたは他のマシン)が分散コンパイルで不思議に思うでしょう。また、大量のメモリと高速ディスク(HDDの代わりにSSD)が大いに役立ちます。64ビットシステムとわいせつな量のRAMがある場合、RAMディスクでコンパイルすると、信じられないほど速度が向上する可能性があります。


1
私の経験では、コンパイラー・キャッシュは実際には分散コンパイルよりも優れたアイデアです。
pqnet 14

RAMディスクとSSDについて言えば、コンパイル速度がそれほど向上しなかったことに非常に驚きました。私の現在のプロジェクト(Android上のJava)は、SSDから45秒以内、RAMディスクから40秒以内にクリーンな状態からコンパイルされます(ツールチェーン全体はソースだけでなくRAMディスクにあります)。劇的な増加ではありません。
ハスペミュレーター14

10

他の人によってまだ言及されていない別の技術的な解決策は、通常のハードドライブの代わりにソリッドステートドライブに切り替えることです。私が取り組んだ以前のプロジェクトでは、SSDによってビルド時間が30分から3分に短縮されました。

もちろん、彼らは高価です。上司の場合、1回限りの投資の価格に対して、失われた開発者の時間の価格を計算します。投資はおそらく数ヶ月でそれ自体の費用がかかります。


6
それは面白い。つまり、ビルド時間の90%がI / Oディスクの待ち時間です。
マイクダンラベイ

90%の減少は見ていませんが、大幅に減少しています。コンパイルは高速化されないようですが、リンクは確実に高速化されます。大規模なプロジェクトに小さな変更を加え(変更でコンパイルがあまり行われない)、再リンクしている場合は、これが得られるでしょう。(これはC ++を使用するVisual Studio 2008です。)
デイビッドソーンリー

1
これはいい考えです。また、RAMの一部をファイルシステムにマウントすると高速に動作し、安価です。
ゴランジョヴィック

2
Ramdiskはさらに高速です(そして安価です)。
SKロジック

1
@ジョン:ええ、よく書かれたコンパイラは(私見)I / Oバウンドする必要があります。
マイクダンラベイ


3

長いコンパイル時間が問題になることもありますが、すでに述べたモジュール化は、そのほとんどを克服するのに役立ちます。

はるかに深刻なのは、まったくコンパイルできない環境で立ち往生していることです。テスト/開発環境に適用するには、すべてのコード変更を別の大陸の別の部門に提出する必要があります。

私は現在そのような環境で作業していますが、変更の最初のバージョンをインストールするためだけに、このシステムには既に1週間以上かかっています(そしてプロジェクトには予算がなくなるまで合計4週間の予算しかありません) (そして、それらがミスをして、ファイルの一部がアプリケーションサーバーによって取得されないため、さらに数日間の遅延を見ています)。現在、マイナーな変更(エラー状態の欠落など、修正が必要なテストで何かを見つけたなど)によって、1日以上遅れることがあります。

このような状況では、コードをコンパイルしようとする前に、エラーがないことをできる限り確実にしようとします。メインフレームプログラミングに戻ったように感じます。メインフレームプログラミングでは、すべてのコンパイルおよびテスト作業に1か月あたり5分間のCPU時間を使用できました。


1
少年、それは地獄からの状況です。メインフレーム時代を覚えています。コードの「デスクチェック」を多数行いました。月へのフライトの無限のシミュレーションなど、そのようにしてどれだけ成し遂げられたかは驚くべきことです。
マイクダンラベイ

3

ビルドに時間がかかったのは簡単に思い出せます。いくつかの緩和アプローチ:

  • ライブラリまたはdllを組み合わせてシステムを構築します。そうすれば、コードを変更するときに、再コンパイルする必要があるのは自分の部分だけです。
  • 機能を実装するために編集する必要があるコード内のポイントの数は、必要な編集の量だけでなく、バ​​グを入れる頻度に影響を与え、compile-debug-edit-compileループを増幅します。DRYなど、コードの冗長性を低下させるものはすべて役立ちます。
  • デバッガを使用していて、デバッガを終了せずに編集、再コンパイル、および続行できる場合は、非常に役立ちます。

2

コンパイルに10分以上かかりますか?マジ?

増分ビルドを行うIDE(Eclipseなど)を使用していますか?そうでない場合は、基本的なコンパイルを数分ではなく数秒で行います。

または、変更をテストするためにアプリ全体を構築する必要がある統合のことについて話しているのですか?その場合、完全なビルドを実行する前に、小規模なテストを見て、主要なバグがコードに含まれていないことを確認してください。


5
10分は短いです。私は、シングルコアマシン、PCHなどでゼロからコンパイルおよびリンクするのに1時間かかったプロジェクトで働いてきました。もちろん、自動リリースビルドを除いて、1つのプロセッサコアでビルドする人はいませんが、それでも...ほぼすべての場所(文字列操作、エラー処理)に含まれるヘッダーの何かを変更する必要がある場合は、気を付けてください。
sbi

2
完全なビルドにコンパイルに48時間かかったシステムで(数年前に)使用されていました。もちろん、フルビルドは金曜日の夕方にのみ開始され、月曜日にオフィスに戻ったときに行われることを願っています。代わりに、必要に応じて小さなモジュールを作成しました(たとえば、単一のDLL)。
jwenting

2
TrueDubに+1できる場合、上記のすべてのコメントに-1。はい、すべてを再コンパイルする場合、非常に長い時間がかかる場合があります。ただし、依存関係の管理について少し考えた場合、10時間の再コンパイルプロジェクト全体で、1分未満でインクリメンタルリコンパイルを行うことができます。少しのインテリジェンスを適用することで膨大な時間を節約できるので、再コンパイルを待つ時間を雇用主が浪費することを恥じるべきです。
ダンク

2
そして、複数のMLoCプロジェクトにたまたま入っている小さな店で働いているなら、それはコードのかなりの部分が古く、10年前に複数の小さなプロジェクトとして始まったということを意味します。依存関係の管理はひどく悪いです。それで、あなたはそのような会社にこれをすべて捨てて、それを書き直すのにさらに10年を使うように言うつもりですか?
sbi

2
@Dunk:それは小さな会社で、数十人未満の開発者がマルチMLoCプロジェクトに取り組んでいます。これは、何百人もの開発者がそうすることとは非常に異なります。年もかかるため、最初から何も書き直すことはできません。私がその考えを嫌ったのと同じくらい、分散コンパイルへの投資は経済的に実行可能であり、書き直しはそうではありませんでした。ああ、それらのインターフェイスを継承しました。:-x彼らが考え出されたとき、私は10年前にそこにいませんでした。(そのコードの多くを変更してTMPを採用し、コンパイル時のエラーを増やし、現場でのエラーを減らしました。)
sbi

2

まず、最初にコンパイルするのになぜそんなに時間がかかるのですか?

  • ご使用の環境(IDE、makeなど)はインクリメンタルビルドをサポートしていますか?全体ではなく、変更のみを再コンパイルしていることを確認してください。
  • マルチコアマシンを使用している場合、IDEは並列コンパイルをサポートする場合があります。Visual Studioがそれを行うという事実を知っています。どうやらgccもそうです。したがって、より良いマシンを入手し、並列コンパイルを有効にします。
  • プリコンパイル済みヘッダーの使用を検討してください。
  • それをすべて試しても、コンパイルがまだ遅い場合は、コードを確認してください。不要な依存関係を探します。前方宣言で十分なヘッダーを含めていますか?PIMPLイディオムを使用して、ヘッダーへの依存を減らすことを検討してください。

それでもやはりビルド時間が遅い場合は、問題を解消してください。多数の小さなテストプロジェクトを作成し、それぞれ個別に作業してください。自動チェックアウトを行い、すべてをビルドし、すべてのユニットテストを自動的に実行する自動化されたナイトリービルドシステムがあることを確認してください。

最後に、変更をテストするのにまだ長い時間がかかる場合は、さらに検討してください。バージョン管理システムで差分を作成し、テストする前にすべての変更を慎重に確認してください。要するに、これはテストの所要時間が長く、システムの状態を調べる能力が限られている組み込みシステム開発に非常によく似ています。

これは、別の考えにつながります。ロギングを使用するようにコードを計測します。この方法では、何十回も再構築して再実行することなく、問題の内容を確認できる場合があります。


2
makeや同様のツールがGCCのコピーをいくつか起動するという事実から、GCCが並列コンパイルをサポートしているかどうかはわかりません。
ザカリーK

1
PIMPLの場合は+1。ビルド時間が制御不能になったプロジェクトに取り組みました。そのプロジェクトでは、各ヘッダーに他のヘッダーがいくつ含まれているかについては気にしませんでした。次のプロジェクトでは、PIMPLを広範囲に使用することでこれを最小限に抑えることを強調しました。2番目のプロジェクトはおそらく最初のプロジェクトの2倍のサイズですが、ビルド時間は引き続き長くなります。
ジェイソンB

1

多面的なアプローチがおそらく必要です:

1)ビルドシステムの高速化。できるだけ多くのコア/ RAM /高速ディスク。大規模なC ++プロジェクトの場合、ディスクは多くの場合リミッターであることがわかるので、高速なものがあることを確認してください。

2)プロジェクトのさらなるモジュール化。変更がすべての完全な再コンパイルを簡単に引き起こさないように、ものを分割します。率直に言って、できるだけ多くの基本的なものを別々のdll / soファイルにプッシュして、プロジェクトの一部を残りの部分から完全に離婚できるようにしてください。

3)環境に応じて、インクリメンタルビルド/分散ビルド/キャッシュ。一部のシステムでは、distcc(分散ビルド)とccache(部分的にビルドされたもののキャッシュ)により、コンパイル時間を大幅に節約できます。

4)ビルドを適切に並列化できることを確認します。特にmakefile環境では、誤ってMakefileをセットアップして並列ビルドができないような状況に陥ることは難しくありません。


0

広範囲なロギングと内部検証は、長い所要時間に役立ちました。ビルドが完了すると、1回の実行で一度に多数の潜在的な問題が明らかになります。

かなり複雑なアルゴリズムや簿記を扱うとき、「実際の」バージョンと並行して非常に単純化されたバージョンを含めると便利です。どの実行でも、有用な参照データが含まれています。


0

@sbiと@Michael Kohneが言ったこと。

ビルドプロセス自体に時間とエネルギーを費やします。むかしむかし、フルビルドに1時間以上かかった堂々とした成熟した製品がありました。ビルドの依存関係が主張するものを修正するために多くの時間とエネルギーが費やされ、その後、実際にあったものを修正/削減しました。ビルド時間は約30分に短縮されました。

ビルドツールを変更すると、さらに落ちました。マルチパートプロジェクトの場合、「scons」はリンクを実行する前にすべてのコンパイルを実行できます。複数のmakefileを使用する「make」は、そのプロジェクトのリンクの前に1つのプロジェクトのコンパイルを実行し、次に進みます。

これにより、個々のコンパイルコマンドをすべて非常に並列に実行できるようになりました。低速マシンでは「distcc」、マルチコアマシンではmake / scons -j8。これにより、フルビルドが数分で完了しました。

別の観点から、自動化された夜間ビルドプロセスを作成します。そうすることで、何か問題がソースリポジトリにコミットされた場合、最初に作業を開始し、問題を確認して修正すると、複数の人が複数の失敗したビルドを(再)実行できなくなります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.