Modulsystem? Compilezeit mit Templates
-
Heii.
Ich nutze in letzter Zeit immer mehr Templates. Eigentlich sogar für fast alles. Nur leider führt das dazu, dass die Compilezeit extrem nach oben geht, sogar so weit, dass ich an vielen Stellen die Templates wieder rausgenommen habe und stattdessen einfach zwei Klassen nutze oder anderes Gefummel.
Meine Projekte kompilieren einfach unerträglich langsam. Sowohl mit dem MSVC als auch mit GCC, wobei letzterer sogar noch ca. 5 (!) mal langsamer ist, da kann man echt Kaffe trinken gehen. (Und das obwohl ich GCC als viel schneller in Erinnerung hatte, woher das wohl kommt?)
Geht euch das auch so? Was macht ihr dagegen? Und wäre es nicht langsam mal Zeit von dem Header/.cpp-Dateien Konzept Abschied zu nehmen und ein Modulsystem zu nutzen, da man bei Templates ja eh gezwungen ist alles in die Header zu packen?
-
Ja, bei mir ist das auch so. Zwar weniger bei eigenen Projekten (nicht zuletzt weil ich mich teilweise darauf achte), aber gerade bei der Verwendung gewisser Boost-Bibliotheken geht die Kompilierzeit extrem in die Höhe. Manchmal helfen Precompiled Headers, aber gerade bei eigenen, sich ständig ändernden Headern hilft das wenig. Ich versuche aber auch, die Verwendung von Templates in Grenzen zu halten. Manchmal sind dynamischere Ansätze (z.B. Strategies statt Policies) geeigneter.
Es gab bereits Vorschläge an das Standardkommitee für ein Modulsystem, auf Stackoverflow gibt es z.B. eine Diskussion dazu.
-
Ich wäge immer ab zwischen
- Keine Flexibilität (you ain't gonna need it...). Im ersten Ansatz programmiere ich das was gebraucht wird und zerbreche mir nicht lange den Kopf auf wie viele Arten ich abstrahieren kann. Oft programmiert man die tollsten abstrakten Schnittstellen oder Templates, um im gesamten Projektlebenszyklus exakt eine Implementierung bereit zustellen. Natürlich programmiert man dabei aber immer mit dem Hintergedanken einfach refaktorisieren zu können. Zusätzlich wird bei passenden Klassen jegliche Implementierung "gepimpelt".
- Laufzeit Polymorphie. Komm ich mit einem starren System nicht weiter denk ich zunächst über Abstraktionen über virtuelle Funktionen nach. Damit lässt sich wunderbar Compilezeit einsparen und die Laufzeitkosten sind zu 90% vernachlässigbar.
- Nur wo ich ganz besonders auf Laufzeit achte und ein flexibles System benötige setze ich Templates ein. Templates sind toll, aber wie du ja selbst feststellst bei übertriebener Anwendung in großen Projekten anstregend.
Das ganze gilt jetzt allerdings für Entwicklung von komplexerer Software. Bei der Entwicklung von Bibliotheken habe ich da schon eher einen anderen Fokus und achte besonders auf ein generisches System. Bei so einer Bibliothek kompiliert man das gesamte Paket aber eher selten, so dass die Zeiten nicht so tragisch sind.
-
Meine Projekte kompilieren einfach unerträglich langsam.
Von wie vielen Minuten redest du? Ansonsten kommt es auf deinen Programmierstil an, bsp. wenn du staendig kompilieren musst, nur um dir sicher zu sein, dass es funktioniert.
-
knivil schrieb:
Meine Projekte kompilieren einfach unerträglich langsam.
Von wie vielen Minuten redest du? Ansonsten kommt es auf deinen Programmierstil an, bsp. wenn du staendig kompilieren musst, nur um dir sicher zu sein, dass es funktioniert.
2 - 6. Hört sich vielleicht nicht nach so viel an, aber wie soll man beim Debuggen denn das ständige Kompilieren vermeiden? Klar, wenn man neu anfängt kann man viel auf einmal schreiben, aber wenn es dann an den Kleinkram geht, wird es unerträglich.
-
Buildest du denn schön brav parallel?
-
C++ schrieb:Geht euch das auch so?
Nein, ganz und gar nicht. Aber ich inkludiere immer sehr wenig und entkopple die <windows.h> oder ähnliche dicke Header von meinem Code weitgehend. Inzwischen wohl nur noch aus Geiz.
C++ schrieb:Was macht ihr dagegen?
Außerdem habe ich einen neuen I7. Sag Deinem Chef, daß Du auch einen brauchst.

C++ schrieb:Und wäre es nicht langsam mal Zeit von dem Header/.cpp-Dateien Konzept Abschied zu nehmen und ein Modulsystem zu nutzen, da man bei Templates ja eh gezwungen ist alles in die Header zu packen?
Ja, es wäre Zeit. Aber nur, weil die Leute das Header/.cpp-Dateien-Konzept nicht raffen. Und wegen des Ärgers mit zyklischen Abhängigkeiten. Wegen der Übersetzungszeit nicht mehr.
Gar nicht mehr.
$ cd /usr/src/linux ; make mrproper ; make defconfig ; time make -j100 real 1m30.998s user 9m58.501s sys 0m41.981sBumm! 90 Sekunden für den Linux-Kernel. Das ist doch nicht mehr wahr.
-
Wäre interessant zu wissen, wie es mit -jAnzahlDerCores aussieht.
-
314159265358979 schrieb:
Wäre interessant zu wissen, wie es mit -jAnzahlDerCores aussieht.
Die Meßschwankungen sind so um ungefähr eine Sekunde.
Es sind 4 Kerne, von denen jeder 2 Threads mit Hyperthreading schafft.-j4: 1m47.917s
-j8: 1:29:736s
(also bringt Hyperthreading nur 20%)
-j100: 1:30:725
(also kosten Prozesswechsel nichts mehr)
-j1000: nicht genug RAM
-j200: 1m29.690s
(also kosten Prozesswechsel gar nichts mehr)Womit wir zu einem eisenharten Fall des Informatik-Aberglaubens kommen, nämlich daß man async arbeiten müßte, um Performance zu bekommen. Why Events Are A Bad Idea (for high-concurrency servers)
-
volkard schrieb:
-j4: 1m47.917s
-j8: 1:29:736s
(also bringt Hyperthreading nur 20%)Ich find 20% eigentlich einen ganz guten Wert, wenn alle vier Kerne bereits voll ausgelastet sind.
-
volkard schrieb:
Gar nicht mehr.
$ cd /usr/src/linux ; make mrproper ; make defconfig ; time make -j100 real 1m30.998s user 9m58.501s sys 0m41.981sBumm! 90 Sekunden für den Linux-Kernel. Das ist doch nicht mehr wahr.
Wieviel Templates sind im Linux-Kernel?
-
Hemeraterahmu schrieb:
Wieviel Templates sind im Linux-Kernel?
Hast du schonmal nen Linux-Kernel kompiliert? Je nach config braucht das schon so seine Minuten. Vor allem sind es wahnsinnig viele Source-files. Da sollte es egal sein, ob ich c- oder cpp-files (mit oder ohne templates) in den Compiler reinwerf.
Worauf volkard raus wollte: Neuerer Prozessor wäre überlegenswert...
Keine Ahnung wie groß
C++ Projekt ist, bissl in den Sourcen rumspielen und neukompilieren dauert bis zu 6 Minuten: Entweder hat er einen Vorkriegs-PC, oder er schert sich überhaupt nicht um Abhängigkeiten (sprich: includen was das Zeug hält, egal ob ich es brauch oder nicht)
-
kratzbürstiges Schwefelei schrieb:
Hemeraterahmu schrieb:
Wieviel Templates sind im Linux-Kernel?
Hast du schonmal nen Linux-Kernel kompiliert? Je nach config braucht das schon so seine Minuten. Vor allem sind es wahnsinnig viele Source-files. Da sollte es egal sein, ob ich c- oder cpp-files (mit oder ohne templates) in den Compiler reinwerf.
Worauf volkard raus wollte: Neuerer Prozessor wäre überlegenswert...
Keine Ahnung wie groß
C++ Projekt ist, bissl in den Sourcen rumspielen und neukompilieren dauert bis zu 6 Minuten: Entweder hat er einen Vorkriegs-PC, oder er schert sich überhaupt nicht um Abhängigkeiten (sprich: includen was das Zeug hält, egal ob ich es brauch oder nicht)Mit den entsprechenden boost includes bekommst du es schnell hin, dass ein File ca. 1 Minute compiliert, auch auf richtig guten Rechnern.

-
Hemeraterahmu schrieb:
Mit den entsprechenden boost includes bekommst du es schnell hin, dass ein File ca. 1 Minute compiliert, auch auf richtig guten Rechnern.

Wir hatten mal einen boost multi index container der alleine 6 Minuten compiliert hat
Aber sowas mus man halt so verstecken, dass es nie neu kompiliert werden muss.
-
brotbernd schrieb:
Aber sowas mus man halt so verstecken, dass es nie neu kompiliert werden muss.
Das ist ja das, was volkard beanstandet - viele scheren sich um forward-deklarations einen Dreck und inkludieren einfach pauschal im Header alles, was thematisch irgendwann mal gebraucht werden könnte.
Auch bei boost-Bibliotheken kommt das gerne mal vor, dass man mehr einbindet als nötig: Wenn eine Klasse einen boost::mutex braucht, um Threadsafe arbeiten zu können, binden viele einfach boost/thread.hpp ein, weil der mutex ja irgendwo in Boost.Thread zu finden ist. Der Compiler rödelt dann lustig über diverse nie genutzte Features, obwohl boost/thread/mutex.hpp der einzige benötigte Header wäre.
PS: auch templates kann man forward-deklarieren...
-
Hemeraterahmu schrieb:
Wieviel Templates sind im Linux-Kernel?
Keine. Aber es sind unglaublich viele große Dateien.
Hemeraterahmu schrieb:
Mit den entsprechenden boost includes bekommst du es schnell hin, dass ein File ca. 1 Minute compiliert, auch auf richtig guten Rechnern.

In produktivem Code berechne ich Primzahlen nicht durch Template-Metaprogrammierung. Wenn man was fettes von boost::spirit verlangt, dann sollte das nicht in einem Header stehen, den man in allen eigenen Dateien inkludiert.
Aber Dir zuliebe habe ich auch mal boost gemessen.
boost compilieren:
real 4m29.966s
user 15m14.844s
sys 0m58.180sUm zu schauen, wieviele Dateien das waren, mache ich mal ccache an.
cache hit (direct) 0
cache hit (preprocessed) 0
cache miss 602
called for link 45
no input file 16
files in cache 1203
Also wohl 602 Dateien und die benutzen boost.
Macht bei 270 Sekunden ca eine halbe Sekunde pro Datei.Ich denke, das mit den Compilezeiten kann man schon ganz entspannt angehen, wenn man nur ein ganz klein Bißchen geizig ist, was vor allem heißt, nur das Benötigte zu inkludieren. Und zum Beispiel mit #ifdef den Compiler rausfinden und was behaupten und dann mit static_assert prüfen, statt mit mit type lists und Prüfung es berechnen zu lassen.