Welche Techniken können verwendet werden, um die C ++ - Kompilierungszeiten zu beschleunigen?
Diese Frage tauchte in einigen Kommentaren zum Programmierstil der Stapelüberlauffrage C ++ auf , und ich bin gespannt, welche Ideen es gibt.
Ich habe eine verwandte Frage gesehen: Warum dauert die C ++ - Kompilierung so lange? , aber das bietet nicht viele Lösungen.
Antworten:
Sprachtechniken
Pimpl Idiom
Schauen Sie sich hier und hier die Pimpl-Sprache an , die auch als undurchsichtige Zeiger- oder Handle-Klassen bezeichnet wird. Dies beschleunigt nicht nur die Kompilierung, sondern erhöht auch die Ausnahmesicherheit in Kombination mit einem nicht werfenden Tausch Funktion. Mit der Pimpl-Sprache können Sie die Abhängigkeiten zwischen Headern reduzieren und den Umfang der Neukompilierung reduzieren, die durchgeführt werden muss.
Vorwärtserklärungen
Verwenden Sie nach Möglichkeit Vorwärtserklärungen . Wenn der Compiler das nur wissen muss
SomeIdentifier
es sich um eine Struktur oder einen Zeiger oder was auch immer handelt, schließen Sie nicht die gesamte Definition ein, sodass der Compiler mehr Arbeit leisten muss als nötig. Dies kann einen Kaskadeneffekt haben und diesen Weg langsamer machen, als sie sein müssen.Die E / A- Streams sind besonders dafür bekannt, Builds zu verlangsamen. Wenn Sie sie in einer Header-Datei benötigen, versuchen Sie, #including
<iosfwd>
anstelle von<iostream>
und #include den<iostream>
Header nur in die Implementierungsdatei aufzunehmen. Der<iosfwd>
Header enthält nur Vorwärtsdeklarationen. Leider haben die anderen Standardheader keinen entsprechenden Deklarationsheader.Bei Funktionssignaturen ist die Referenzübergabe der Wertübergabe vorzuziehen. Dadurch entfällt die Notwendigkeit, # die entsprechenden Typdefinitionen in die Header-Datei aufzunehmen, und Sie müssen den Typ nur vorwärts deklarieren. Bevorzugen Sie natürlich const-Verweise gegenüber nicht-const-Verweisen, um obskure Fehler zu vermeiden, aber dies ist ein Problem für eine andere Frage.
Wachbedingungen
Verwenden Sie Schutzbedingungen, um zu verhindern, dass Header-Dateien mehrmals in einer einzelnen Übersetzungseinheit enthalten sind.
Wenn Sie sowohl das Pragma als auch das ifndef verwenden, erhalten Sie die Portabilität der einfachen Makrolösung sowie die Optimierung der Kompilierungsgeschwindigkeit, die einige Compiler in Gegenwart von ausführen können
pragma once
Direktive durchführen können.Reduzieren Sie die gegenseitige Abhängigkeit
Je modularer und weniger voneinander abhängig Ihr Code-Design im Allgemeinen ist, desto seltener müssen Sie alles neu kompilieren. Sie können auch den Arbeitsaufwand reduzieren, den der Compiler gleichzeitig für einen einzelnen Block leisten muss, da er weniger zu verfolgen hat.
Compiler-Optionen
Vorkompilierte Header
Diese werden verwendet, um einen gemeinsamen Abschnitt der enthaltenen Überschriften einmal für viele Übersetzungseinheiten zu kompilieren. Der Compiler kompiliert es einmal und speichert seinen internen Status. Dieser Status kann dann schnell geladen werden, um einen Vorsprung beim Kompilieren einer anderen Datei mit denselben Headern zu erhalten.
Achten Sie darauf, dass Sie nur selten geänderte Inhalte in die vorkompilierten Header aufnehmen, da Sie sonst häufiger als nötig vollständige Neuerstellungen durchführen können. Dies ist ein guter Ort für STL- Header und andere Bibliotheks-Include-Dateien.
ccache ist ein weiteres Dienstprogramm, das Caching-Techniken nutzt, um die Dinge zu beschleunigen.
Verwenden Sie Parallelität
Viele Compiler / IDEs unterstützen die Verwendung mehrerer Kerne / CPUs, um gleichzeitig zu kompilieren. Verwenden Sie in GNU Make (normalerweise mit GCC verwendet) die
-j [N]
Option. In Visual Studio gibt es unter den Einstellungen eine Option, mit der mehrere Projekte parallel erstellt werden können. Sie können die Option auch verwenden/MP
für Paralellismus auf Dateiebene verwenden, anstatt nur Paralellismus auf Projektebene.Andere parallele Dienstprogramme:
Verwenden Sie eine niedrigere Optimierungsstufe
Je mehr der Compiler zu optimieren versucht, desto schwieriger muss er arbeiten.
Gemeinsame Bibliotheken
Das Verschieben Ihres weniger häufig geänderten Codes in Bibliotheken kann die Kompilierungszeit verkürzen. Durch die Verwendung gemeinsam genutzter Bibliotheken (
.so
oder.dll
) können Sie auch die Verknüpfungszeit verkürzen.Holen Sie sich einen schnelleren Computer
Mehr RAM, schnellere Festplatten (einschließlich SSDs) und mehr CPUs / Kerne wirken sich auf die Kompilierungsgeschwindigkeit aus.
quelle
Ich arbeite am STAPL-Projekt, einer C ++ - Bibliothek mit starken Vorlagen. Hin und wieder müssen wir alle Techniken überdenken, um die Kompilierungszeit zu verkürzen. Hier habe ich die Techniken zusammengefasst, die wir verwenden. Einige dieser Techniken sind bereits oben aufgeführt:
Finden der zeitaufwändigsten Abschnitte
Obwohl es keine nachgewiesene Korrelation zwischen den Symbollängen und der Kompilierungszeit gibt, haben wir beobachtet, dass kleinere durchschnittliche Symbolgrößen die Kompilierungszeit auf allen Compilern verbessern können. Ihr erstes Ziel ist es also, die größten Symbole in Ihrem Code zu finden.
Methode 1 - Sortieren Sie Symbole nach Größe
Mit dem
nm
Befehl können Sie die Symbole anhand ihrer Größe auflisten:In diesem Befehl
--radix=d
können Sie die Größen in Dezimalzahlen anzeigen (Standard ist hexadezimal). Sehen Sie sich nun das größte Symbol an, um festzustellen, ob Sie die entsprechende Klasse aufteilen können, und versuchen Sie, sie neu zu gestalten, indem Sie die nicht mit Vorlagen versehenen Teile in einer Basisklasse berücksichtigen oder die Klasse in mehrere Klassen aufteilen.Methode 2 - Sortieren Sie Symbole nach Länge
Sie können die reguläre ausführen
nm
Befehl und an Ihr Lieblingsskript ( AWK , Python usw.) weiterleiten , um die Symbole nach ihrer Länge zu sortieren . Basierend auf unserer Erfahrung identifiziert diese Methode die größten Probleme, Kandidaten besser zu machen als Methode 1.Methode 3 - Verwenden Sie Templight
" Templight ist ein Clang- basiertes Tool zum Profilieren des Zeit- und Speicherverbrauchs von Vorlageninstanziierungen und zum Durchführen interaktiver Debugging-Sitzungen, um einen Einblick in den Vorlageninstanziierungsprozess zu erhalten."
Sie können Templight installieren, indem Sie auschecken LLVM und Clang ( Anweisungen ) auschecken und den Templight-Patch darauf anwenden. Die Standardeinstellung für LLVM und Clang ist Debugging und Assertions. Diese können sich erheblich auf Ihre Kompilierungszeit auswirken. Templight benötigt anscheinend beides, daher müssen Sie die Standardeinstellungen verwenden. Die Installation von LLVM und Clang sollte ungefähr eine Stunde dauern.
Nach dem Anwenden des Patches können
templight++
Sie den Code verwenden, der sich in dem Build-Ordner befindet, den Sie bei der Installation angegeben haben.Stellen Sie sicher, dass dies
templight++
in Ihrem PFAD ist. Fügen Sie nun zum Kompilieren die folgenden Schalter zu Ihrem hinzuCXXFLAGS
Ihrem Makefile oder zu Ihren Befehlszeilenoptionen hinzu:Oder
Nach Abschluss der Kompilierung werden im selben Ordner eine .trace.memory.pbf und eine .trace.pbf generiert. Um diese Traces zu visualisieren, können Sie die Templight-Tools verwenden, mit denen diese in andere Formate konvertiert werden können. Befolgen Sie diese Anweisungen , um templight-convert zu installieren. Wir verwenden normalerweise die Callgrind-Ausgabe. Sie können die GraphViz-Ausgabe auch verwenden, wenn Ihr Projekt klein ist:
Die generierte Callgrind-Datei kann mit geöffnet werden kcachegrind in dem Sie die zeit- und speicherintensivste Instanziierung verfolgen können.
Reduzieren der Anzahl der Vorlageninstanziierungen
Obwohl es keine genaue Lösung gibt, um die Anzahl der Vorlageninstanziierungen zu verringern, gibt es einige Richtlinien, die helfen können:
Refactor-Klassen mit mehr als einem Vorlagenargument
Wenn Sie beispielsweise eine Klasse haben,
und beide
T
undU
können 10 verschiedene Optionen haben. Sie haben die möglichen Vorlageninstanziierungen dieser Klasse auf 100 erhöht. Eine Möglichkeit, dies zu beheben, besteht darin, den gemeinsamen Teil des Codes in eine andere Klasse zu abstrahieren. Die andere Methode ist die Verwendung der Vererbungsinversion (Umkehrung der Klassenhierarchie). Stellen Sie jedoch sicher, dass Ihre Entwurfsziele nicht beeinträchtigt werden, bevor Sie diese Technik verwenden.Refactor-Code ohne Vorlagen für einzelne Übersetzungseinheiten
Mit dieser Technik können Sie den allgemeinen Abschnitt einmal kompilieren und später mit Ihren anderen TUs (Übersetzungseinheiten) verknüpfen.
Externe Vorlageninstanziierungen verwenden (seit C ++ 11)
Wenn Sie alle möglichen Instanziierungen einer Klasse kennen, können Sie mit dieser Technik alle Fälle in einer anderen Übersetzungseinheit kompilieren.
Zum Beispiel in:
Wir wissen, dass diese Klasse drei mögliche Instanziierungen haben kann:
Fügen Sie das Obige in eine Übersetzungseinheit ein und verwenden Sie das Schlüsselwort extern in Ihrer Header-Datei unterhalb der Klassendefinition:
Diese Technik kann Ihnen Zeit sparen, wenn Sie verschiedene Tests mit einem gemeinsamen Satz von Instanziierungen kompilieren.
Verwenden Sie Unity Builds
Die ganze Idee hinter Unity Builds besteht darin, alle von Ihnen verwendeten .cc-Dateien in eine Datei aufzunehmen und diese Datei nur einmal zu kompilieren. Mit dieser Methode können Sie vermeiden, gemeinsame Abschnitte verschiedener Dateien wiederherzustellen, und wenn Ihr Projekt viele gemeinsame Dateien enthält, würden Sie wahrscheinlich auch beim Zugriff auf die Festplatte sparen.
Als Beispiel nehmen wir an , Sie drei Dateien haben
foo1.cc
,foo2.cc
,foo3.cc
und sie alle sindtuple
von STL . Sie können eine erstellenfoo-all.cc
, die wie folgt aussieht:Sie kompilieren diese Datei nur einmal und reduzieren möglicherweise die allgemeinen Instanziierungen zwischen den drei Dateien. Es ist schwer vorherzusagen, ob die Verbesserung signifikant sein kann oder nicht. Eine offensichtliche Tatsache ist jedoch, dass Sie die Parallelität in Ihren Builds verlieren würden (Sie können die drei Dateien nicht mehr gleichzeitig kompilieren).
Wenn eine dieser Dateien viel Speicherplatz beansprucht, geht Ihnen möglicherweise der Speicherplatz aus, bevor die Kompilierung abgeschlossen ist. Auf einigen Compilern, wie z. B. GCC , kann dies zu ICE (Internal Compiler Error) Ihres Compilers führen, da nicht genügend Speicher vorhanden ist. Verwenden Sie diese Technik also nur, wenn Sie alle Vor- und Nachteile kennen.
Vorkompilierte Header
Vorkompilierte Header (PCHs) können Ihnen beim Kompilieren viel Zeit sparen, indem Sie Ihre Header-Dateien zu einer Zwischendarstellung kompilieren, die von einem Compiler erkannt wird. Um vorkompilierte Header-Dateien zu generieren, müssen Sie Ihre Header-Datei nur mit Ihrem regulären Kompilierungsbefehl kompilieren. Zum Beispiel auf GCC:
Dadurch wird im selben Ordner ein
YOUR_HEADER.hpp.gch file
(.gch
ist die Erweiterung für PCH-Dateien in GCC) generiert . Dies bedeutet, dassYOUR_HEADER.hpp
der Compiler , wenn Sie in eine andere Datei aufnehmen, IhreYOUR_HEADER.hpp.gch
anstelle vonYOUR_HEADER.hpp
im selben Ordner verwendet.Bei dieser Technik gibt es zwei Probleme:
all-my-headers.hpp
. B. ). Das bedeutet aber, dass Sie die neue Datei an allen Stellen einfügen müssen. Glücklicherweise hat GCC eine Lösung für dieses Problem. Verwenden Sie-include
und geben Sie ihm die neue Header-Datei. Mit dieser Technik können Sie verschiedene Dateien durch Kommas trennen.Beispielsweise:
Verwenden Sie unbenannte oder anonyme Namespaces
Unbenannte Namespaces (auch anonyme Namespaces genannt) können die generierten Binärgrößen erheblich reduzieren. Unbenannte Namespaces verwenden interne Verknüpfungen. Dies bedeutet, dass die in diesen Namespaces generierten Symbole für andere TU (Übersetzungs- oder Kompilierungseinheiten) nicht sichtbar sind. Compiler generieren normalerweise eindeutige Namen für unbenannte Namespaces. Dies bedeutet, wenn Sie eine Datei foo.hpp haben:
Und Sie fügen diese Datei zufällig in zwei TUs ein (zwei .cc-Dateien und kompilieren sie separat). Die beiden foo-Vorlageninstanzen sind nicht identisch. Dies verstößt gegen die One Definition Rule (ODR). Aus dem gleichen Grund wird davon abgeraten, unbenannte Namespaces in den Header-Dateien zu verwenden. Sie können sie auch in Ihren
.cc
Dateien verwenden, um zu vermeiden, dass Symbole in Ihren Binärdateien angezeigt werden. In einigen Fällen führte das Ändern aller internen Details für eine.cc
Datei zu einer Reduzierung der generierten Binärgrößen um 10%.Sichtbarkeitsoptionen ändern
In neueren Compilern können Sie Ihre Symbole so auswählen, dass sie in den Dynamic Shared Objects (DSOs) entweder sichtbar oder unsichtbar sind. Im Idealfall kann das Ändern der Sichtbarkeit die Compilerleistung verbessern, Verbindungszeitoptimierungen (LTOs) und generierte Binärgrößen generieren. Wenn Sie sich die STL-Header-Dateien in GCC ansehen, sehen Sie, dass sie weit verbreitet sind. Um die Auswahl der Sichtbarkeit zu ermöglichen, müssen Sie Ihren Code pro Funktion, pro Klasse, pro Variable und vor allem pro Compiler ändern.
Mithilfe der Sichtbarkeit können Sie die Symbole, die Sie als privat betrachten, vor den generierten freigegebenen Objekten ausblenden. In GCC können Sie die Sichtbarkeit von Symbolen steuern, indem Sie standardmäßig oder ausgeblendet an die
-visibility
Option Ihres Compilers übergeben. Dies ähnelt in gewisser Weise dem unbenannten Namespace, ist jedoch aufwändiger und aufdringlicher.Wenn Sie die Sichtbarkeiten pro Fall angeben möchten, müssen Sie Ihren Funktionen, Variablen und Klassen die folgenden Attribute hinzufügen:
Die Standardsichtbarkeit in GCC ist Standard (öffentlich). Wenn Sie die oben genannte
-shared
Methode als gemeinsam genutzte Bibliothek ( ) kompilieren, wird diefoo2
Klassefoo3
in anderen TUs nicht sichtbar (foo1
undfoo4
ist auch sichtbar). Wenn Sie mit kompilieren,-visibility=hidden
ist nurfoo1
dann sichtbar. Sogarfoo4
wäre versteckt.Weitere Informationen zur Sichtbarkeit finden Sie im GCC-Wiki .
quelle
Ich würde diese Artikel aus "Games from Within, Indie Game Design und Programmierung" empfehlen:
Zugegeben, sie sind ziemlich alt - Sie müssen alles mit den neuesten Versionen (oder Versionen, die Ihnen zur Verfügung stehen) erneut testen, um realistische Ergebnisse zu erzielen. In jedem Fall ist es eine gute Quelle für Ideen.
quelle
Eine Technik, die in der Vergangenheit für mich sehr gut funktioniert hat: Kompilieren Sie nicht mehrere C ++ - Quelldateien unabhängig voneinander, sondern generieren Sie eine C ++ - Datei, die alle anderen Dateien enthält, wie folgt:
Dies bedeutet natürlich, dass Sie den gesamten enthaltenen Quellcode neu kompilieren müssen, falls sich eine der Quellen ändert, damit sich der Abhängigkeitsbaum verschlechtert. Das Kompilieren mehrerer Quelldateien als eine Übersetzungseinheit ist jedoch schneller (zumindest in meinen Experimenten mit MSVC und GCC) und generiert kleinere Binärdateien. Ich vermute auch, dass der Compiler mehr Potenzial für Optimierungen hat (da er mehr Code auf einmal sehen kann).
Diese Technik bricht in verschiedenen Fällen; Beispielsweise wird der Compiler aussteigen, wenn zwei oder mehr Quelldateien eine globale Funktion mit demselben Namen deklarieren. Ich konnte diese Technik in keiner der anderen Antworten finden, deshalb erwähne ich sie hier.
Für das, was es wert ist, verwendete das KDE-Projekt seit 1999 genau dieselbe Technik, um optimierte Binärdateien zu erstellen (möglicherweise für eine Veröffentlichung). Der Wechsel zum Build-Konfigurationsskript wurde aufgerufen
--enable-final
. Aus archäologischem Interesse habe ich den Beitrag ausgegraben, in dem diese Funktion angekündigt wurde: http://lists.kde.org/?l=kde-devel&m=92722836009368&w=2quelle
<core-count> + N
Unterlisten aufgeteilt werden, die parallel kompiliert werden, wobeiN
eine geeignete Ganzzahl vorliegt (abhängig vom Systemspeicher und der Art und Weise, wie der Computer anderweitig verwendet wird).Zu diesem Thema gibt es ein ganzes Buch mit dem Titel Large-Scale C ++ Software Design (geschrieben von John Lakos).
Das Buch datiert Vorlagen vor, sodass zum Inhalt dieses Buches hinzugefügt wird, dass "auch die Verwendung von Vorlagen den Compiler langsamer machen kann".
quelle
Ich werde nur auf meine andere Antwort verweisen: Wie reduzieren SIE die Kompilierungszeit und die Verknüpfungszeit für Visual C ++ - Projekte (natives C ++)? . Ein weiterer Punkt, den ich hinzufügen möchte, der jedoch häufig Probleme verursacht, ist die Verwendung vorkompilierter Header. Verwenden Sie sie jedoch nur für Teile, die sich kaum ändern (z. B. GUI-Toolkit-Header). Andernfalls kosten sie Sie mehr Zeit als Sie am Ende sparen.
Eine andere Option ist, wenn Sie mit GNU make arbeiten, die
-j<N>
Option zu aktivieren:Normalerweise habe ich es,
3
da ich hier einen Dual Core habe. Anschließend werden Compiler für verschiedene Übersetzungseinheiten parallel ausgeführt, sofern keine Abhängigkeiten zwischen ihnen bestehen. Die Verknüpfung kann nicht parallel erfolgen, da nur ein Verknüpfungsprozess alle Objektdateien miteinander verknüpft.Der Linker selbst kann jedoch mit einem Thread versehen werden, und genau das tut der ELF- Linker. Es handelt sich um optimierten C ++ - Thread-Code, der ELF-Objektdateien eine Größenordnung schneller verknüpfen soll als der alte (und tatsächlich in binutils enthalten war ).
GNU gold
ld
quelle
Hier sind einige:
make -j2
ein gutes Beispiel).-O1
als-O2
oder-O3
).quelle
-j12
um herum-j18
waren erheblich schneller als-j8
, wie Sie vorschlagen. Ich frage mich, wie viele Kerne Sie haben können, bevor die Speicherbandbreite zum begrenzenden Faktor wird ...-j
2x die Anzahl der tatsächlichen Kerne.Wenn Sie alle oben genannten Code-Tricks angewendet haben (Vorwärtsdeklarationen, Reduzierung der Header-Aufnahme in öffentlichen Headern auf das Minimum, Verschieben der meisten Details in die Implementierungsdatei mit Pimpl ...) und sprachlich nichts anderes erreicht werden kann, sollten Sie Ihr Build-System in Betracht ziehen . Wenn Sie Linux verwenden, sollten Sie distcc (verteilter Compiler) und ccache (Cache-Compiler) verwenden.
Der erste, distcc, führt den Präprozessorschritt lokal aus und sendet dann die Ausgabe an den ersten verfügbaren Compiler im Netzwerk. Es erfordert die gleichen Compiler- und Bibliotheksversionen in allen konfigurierten Knoten im Netzwerk.
Letzterer, ccache, ist ein Compiler-Cache. Der Präprozessor wird erneut ausgeführt und anschließend mit einer internen Datenbank (in einem lokalen Verzeichnis gespeichert) überprüft, ob diese Präprozessordatei bereits mit denselben Compilerparametern kompiliert wurde. Wenn dies der Fall ist, wird nur die Binärdatei angezeigt und vom ersten Lauf des Compilers ausgegeben.
Beide können gleichzeitig verwendet werden, so dass ccache, wenn es keine lokale Kopie hat, diese über das Netz mit distcc an einen anderen Knoten senden kann, oder die Lösung einfach ohne weitere Verarbeitung injizieren kann.
quelle
Als ich das College verließ, hatte der erste echte produktionswürdige C ++ - Code, den ich sah, diese arkanen # ifndef ... # endif-Direktiven dazwischen, in denen die Header definiert waren. Ich fragte den Mann, der den Code auf sehr naive Weise über diese übergreifenden Dinge schrieb, und wurde in die Welt der groß angelegten Programmierung eingeführt.
Zurück zum Punkt: Die Verwendung von Anweisungen zur Vermeidung doppelter Headerdefinitionen war das erste, was ich gelernt habe, wenn es darum ging, die Kompilierungszeiten zu verkürzen.
quelle
Mehr RAM.
Jemand sprach in einer anderen Antwort über RAM-Laufwerke. Ich habe dies mit einem 80286 und Turbo C ++ (zeigt Alter) gemacht und die Ergebnisse waren phänomenal. Wie war der Datenverlust beim Absturz der Maschine.
quelle
Verwenden Sie Vorwärtsdeklarationen, wo Sie können. Wenn eine Klassendeklaration nur einen Zeiger oder Verweis auf einen Typ verwendet, können Sie ihn einfach weiterleiten und den Header für den Typ in die Implementierungsdatei aufnehmen.
Beispielsweise:
Weniger Includes bedeuten viel weniger Arbeit für den Präprozessor, wenn Sie es genug tun.
quelle
Sie können Unity Builds verwenden .
.
quelle
Verwenden
Wenn sie also mehr als einmal in einer Übersetzungseinheit enthalten sind, wird der Text der Kopfzeile nur einmal eingefügt und analysiert.
quelle
Nur der Vollständigkeit halber: Ein Build kann langsam sein, weil das Build-System dumm ist und weil der Compiler lange braucht, um seine Arbeit zu erledigen.
Lesen Sie Recursive Make Considered Harmful (PDF), um dieses Thema in Unix-Umgebungen zu diskutieren.
quelle
Aktualisieren Sie Ihren Computer
Dann haben Sie alle Ihre anderen typischen Vorschläge
quelle
Ich hatte eine Idee zur Verwendung eines RAM-Laufwerks . Es stellte sich heraus, dass es für meine Projekte doch keinen großen Unterschied macht. Aber dann sind sie noch ziemlich klein. Versuch es! Es würde mich interessieren, wie sehr es geholfen hat.
quelle
Dynamische Verknüpfungen (.so) können viel schneller sein als statische Verknüpfungen (.a). Besonders wenn Sie ein langsames Netzlaufwerk haben. Dies liegt daran, dass Sie den gesamten Code in der .a-Datei haben, der verarbeitet und ausgeschrieben werden muss. Außerdem muss eine viel größere ausführbare Datei auf die Festplatte geschrieben werden.
quelle
Nicht über die Kompilierungszeit, sondern über die Erstellungszeit:
Verwenden Sie ccache, wenn Sie dieselben Dateien neu erstellen müssen, wenn Sie an Ihren Builddateien arbeiten
Verwenden Sie Ninja-Build anstelle von make. Ich kompiliere gerade ein Projekt mit ~ 100 Quelldateien und alles wird von ccache zwischengespeichert. machen braucht 5 Minuten, Ninja weniger als 1.
Sie können Ihre Ninja-Dateien aus cmake mit generieren
-GNinja
.quelle
Wo verbringst du deine Zeit? Sind Sie CPU-gebunden? Speicher gebunden? Festplattengebunden? Können Sie mehr Kerne verwenden? Mehr RAM? Benötigen Sie RAID? Möchten Sie einfach die Effizienz Ihres aktuellen Systems verbessern?
Haben Sie sich unter gcc / g ++ den Ccache angesehen ? Es kann hilfreich sein, wenn Sie
make clean; make
viel tun .quelle
Schnellere Festplatten.
Compiler schreiben viele (und möglicherweise riesige) Dateien auf die Festplatte. Arbeiten Sie mit SSD anstelle einer typischen Festplatte, und die Kompilierungszeiten sind viel kürzer.
quelle
Unter Linux (und möglicherweise einigen anderen * NIXes) können Sie die Kompilierung wirklich beschleunigen, indem Sie NICHT auf die Ausgabe starren und zu einem anderen TTY wechseln .
Hier ist das Experiment: printf verlangsamt mein Programm
quelle
Netzwerkfreigaben verlangsamen Ihren Build drastisch, da die Suchlatenz hoch ist. Für so etwas wie Boost hat es einen großen Unterschied gemacht, obwohl unser Netzwerkfreigabe-Laufwerk ziemlich schnell ist. Die Zeit zum Kompilieren eines Toy Boost-Programms stieg von etwa 1 Minute auf 1 Sekunde, als ich von einer Netzwerkfreigabe zu einer lokalen SSD wechselte.
quelle
Wenn Sie einen Multicore-Prozessor haben, unterstützen sowohl Visual Studio (2005 und höher) als auch GCC Multiprozessor-Kompilierungen. Es ist etwas zu aktivieren, wenn Sie die Hardware haben, sicher.
quelle
Obwohl dies keine "Technik" ist, konnte ich nicht herausfinden, wie Win32-Projekte mit vielen Quelldateien schneller kompiliert wurden als mein leeres Projekt "Hello World". Daher hoffe ich, dass dies jemandem hilft, wie es mir getan hat.
In Visual Studio ist eine Option zum Erhöhen der Kompilierungszeiten die inkrementelle Verknüpfung ( / INCREMENTAL ). Es ist nicht kompatibel mit Link-Time Code Generation ( / LTCG ). Denken Sie also daran, die inkrementelle Verknüpfung zu deaktivieren, wenn Sie Release-Builds durchführen.
quelle
/INCREMENTAL
nur im Debug-ModusAb Visual Studio 2017 können Sie einige Compiler-Metriken darüber erstellen, was Zeit kostet.
Fügen Sie diese Parameter zu C / C ++ -> Befehlszeile (Zusätzliche Optionen) im Projekteigenschaftenfenster hinzu:
/Bt+ /d2cgsummary /d1reportTime
Weitere Informationen finden Sie in diesem Beitrag .
quelle
Wenn Sie anstelle einer statischen Verknüpfung eine dynamische Verknüpfung verwenden, wird der Compiler schneller und spürbarer.
Wenn Sie t Cmake verwenden, aktivieren Sie die Eigenschaft:
Build Release mit statischer Verknüpfung kann optimiert werden.
quelle