Blog 4 Min. Lesezeit

Die Bedeutung verteilter Build-Systeme für C++

Diesen Artikel teilen
The Importance of C++ Distributed Build Systems

Wenn Sie als C++-Entwickler schon einmal ein C#- oder Java-Projekt gebaut haben, waren Sie vielleicht überrascht, wie viel schneller der Build-Prozess im Vergleich zu C++ sein kann. Bei manchen C++-Projekten dauert ein Build nur wenige Minuten, bei anderen – abhängig von der Projektgröße – mehrere Stunden. Selbst wenn die Kompilierungsphase auf alle verfügbaren Prozessorkerne parallelisiert wird, können C++-Builds deutlich länger dauern als Builds in anderen Sprachen. Einige Gründe dafür werden in dieser hilfreichen Stack-Overflow-Antwort:

  • Header-Dateien:Jede einzelne Übersetzungseinheit erfordert Hunderte oder sogar Tausende Header, die 1. geladen und 2. kompiliert werden müssen. Üblicherweise muss jeder davon für jede Übersetzungseinheit erneut kompiliert werden, weil der Präprozessor dafür sorgt, dass das Ergebnis der Kompilierung eines Headersmight zwischen den einzelnen Übersetzungseinheiten variieren kann. (In einer Übersetzungseinheit kann beispielsweise ein Makro definiert sein, das den Inhalt des Headers verändert.) Dies ist wahrscheinlich dertheHauptgrund, denn dadurch müssen für jede Übersetzungseinheit enorme Codemengen kompiliert werden. Zusätzlich muss jeder Header mehrfach kompiliert werden – einmal für jede Übersetzungseinheit, die ihn einbindet.
  • Linken:Nach der Kompilierung müssen alle Objektdateien miteinander gelinkt werden. Dabei handelt es sich im Wesentlichen um einen monolithischen Prozess, der sich nur schwer parallelisieren lässt und das gesamte Projekt verarbeiten muss.
  • Parsing:Die Syntax ist äußerst aufwendig zu parsen, hängt stark vom Kontext ab und lässt sich nur schwer eindeutig auflösen. Das kostet viel Zeit.
  • Templates: In C#, List<T>ist der einzige Typ, der kompiliert wird – unabhängig davon, wie viele Instanziierungen von List im Programm vorhanden sind. In C++ hingegenvector<int> is a completely separate type from vector<float>, and each one will have to be compiled separately.

Was passiert, wenn der Build-Prozess langsam ist?

Dauert ein Build zehn Minuten, verliert das Unternehmen entsprechend zehn Minuten multipliziert mit der Anzahl der täglich ausgeführten Builds. Die Gesamtkosten hängen außerdem von der Zahl der Entwickler ab. Je mehr Entwickler beteiligt sind, desto mehr Builds werden ausgeführt und desto größer fällt der Produktivitätsverlust aus.

The IncrediBuild-ROI-Rechner liefert eine Schätzung des Zeitverlusts, wenn ein Team aus X Entwicklern besteht und jeder Build Y Minuten dauert. Der Rechner ist jedoch eher optimistisch, da versteckte Kosten nicht berücksichtigt werden können. Startet ein Entwickler beispielsweise einen Build und muss zehn Minuten warten, wechselt er möglicherweise zu einer anderen Tätigkeit, etwa zum Surfen im Web, und wird abgelenkt. So kann aus einer Unterbrechung von zehn Minuten leicht eine Pause von 15 oder 20 Minuten werden.

Ein schneller Build hilft Entwicklern, sich auf den Code zu konzentrieren, an dem sie gerade arbeiten.

Wie lässt sich der Build-Prozess von C++-Projekten optimieren? Verschiedene Techniken können helfen, den Build-Prozess zu optimieren; einige davon sind hier aufgeführt

  • Pimpl-Idiom
  • Vorwärtsdeklarationen
  • Include Guards
  • Abhängigkeiten reduzieren
  • Und natürlich eine der am häufigsten eingesetzten Techniken: vorkompilierte Header

Die oben genannten Techniken haben jedoch einige Nachteile:

  • Es ist schwierig sicherzustellen, dass diese Maßnahmen tatsächlich konsequent umgesetzt werden; regelmäßige Code-Reviews sind erforderlich.
  • Selbst wenn diese Maßnahmen korrekt umgesetzt werden, kann die Zeitersparnis begrenzt bleiben, und bei sehr großen Projekten können Builds weiterhin mehrere Stunden dauern.
  • Den Code ausschließlich wegen Problemen mit der Build-Zeit zu verändern, ist grundsätzlich keine gute Idee. Design und Implementierung sollten unabhängig vom verwendeten Build-Prozess erfolgen.

Verteilte Build-Systeme für C++ schaffen Abhilfe

Ein verteiltes Build-System verteilt die Kompilierung des Codes auf mehrere Rechner in einem Netzwerk. Das Ergebnis sollte dabei stets identisch mit einer lokalen Kompilierung sein.

Es gibt mehrere interessante verteilte Build-Systeme für C++. Persönlich habe ich bisher nur IncrediBuild.

IncrediBuild ist eine von IncrediBuild Ltd. entwickelte Grid-Computing-Software-Suite. Sie beschleunigt rechenintensive Aufgaben, indem diese über ein Netzwerk verteilt werden. Zu den wichtigsten Einsatzgebieten zählen das Kompilieren von Quellcode, Software-Builds im Allgemeinen sowie weitere Aufgaben der Softwareentwicklung. Jobs können auf mehrere Rechner im Netzwerk verteilt werden, sodass durch zusätzliche Ressourcen deutlich mehr Rechenleistung zur Verfügung steht als auf dem Rechner, der den Vorgang gestartet hat.

IncrediBuild hat uns geholfen, die Build-Zeiten deutlich zu verkürzen und mehr Zeit für produktive Aufgaben zu gewinnen.

Wenn Ihr C++-Build-Prozess zu lange dauert, sollten Sie ein verteiltes Build-System in Betracht ziehen. Prüfen Sie die verfügbaren Werkzeuge und wählen Sie dasjenige aus, das Ihre Anforderungen am besten erfüllt.

Diesen Artikel teilen