2008-12-31 7 views
11

Ich frage mich, was macht den primären Java-Compiler (javac by sun) so schnell bei der Kompilierung?Was macht den Java-Compiler so schnell?

.. ebenso wie der C# .NET-Compiler von Microsoft.

ich sie mit C++ Compiler (wie G ++) bin im Vergleich, so vielleicht sollte meine Frage gewesen sein, was Compiler so langsam :) C++ macht

+0

Was vergleichen Sie? Die Zeit, die benötigt wird, um eine Anwendung aus der Quelle oder die Laufzeitleistung zu kompilieren? –

+2

Könnte mit einigen Beispielen interessanter sein. Einige Messungen mit Timings + Anzahl der Codezeilen. –

+0

Ich vergleiche die Kompilierungszeit, nicht die Laufzeit. – Lawand

Antwort

16

Diese Frage war schön beantwortet in diesem: Why does C++ compilation take so long? (wie jalf im Abschnitt Kommentare hervorgehoben)

Grundsätzlich ist es das fehlende Module Konzept von C++, und die aggressive Optimierung durch den Compiler.

+0

Sicher machen C# und Java nur die Hälfte der Arbeit, die sie zu ByteCode kompilieren und aufhören zu verlassen Rest des Jobs für, wenn der Code ausgeführt wird. C++ macht alles auf einmal. Andere Faktoren wie C++ mit riesigen Text-basierten Header-Dateien für jede Kompilierung hilft auch nicht. – AnthonyLambert

2

Der C++ Compiler müssen alle Header-Dateien wiederholt kompilieren und es gibt viele von ihnen, so ist dies eine Sache, die es verlangsamt.

+0

Man könnte vorgefertigte Header verwenden, um die Geschwindigkeit zu erhöhen. http://en.wikipedia.org/wiki/Precompiled_header –

6

Ich denke, der schwierigste Teil ist nicht die Notwendigkeit, die Header-Dateien zu kompilieren (es sei denn, sie sind wirklich groß, aber Sie können in diesem Fall vorkompilierte Header verwenden). Der schlimmste Teil ist immer die Tatsache, dass die C++ - Grammatik zu stark kontextsensitiv ist. Trotz der Tatsache, dass ich C++ mag, tut mir jeder leid, der einen C++ Parser schreiben muss.

+6

Mach dir keine Sorgen - das ist über 10-20 Menschen auf der Welt :) – MSalters

1

Ich denke, ein Teil davon ist die Komplexität der Sprachen. C++ ist unglaublich änderbar, mit der Fähigkeit, so ziemlich jeden Operator oder jede Syntax zu überschreiben (wie das Überschreiben des() Operators). Dies bedeutet, dass der Compiler eine Menge mehr Arbeit nur tun muss, um festzustellen, welche Operationen tatsächlich ausgeführt werden, selbst für einfache Dinge. Java und C# haben dieses Problem nicht, da die Syntax fest ist und im Allgemeinen viel einfacher zu parsen ist.

2

Eine der zeitaufwendigeren Aufgaben beim Kompilieren ist die Codeoptimierung.

Javac führt bei der Kompilierung nur eine sehr geringe Optimierung des Codes durch. Die Optimierung wird stattdessen von der JVM beim Ausführen der Anwendung durchgeführt.

Ein C/C++ muss beim Kompilieren optimiert werden, da die Optimierung des kompilierten Maschinencodes schwierig ist.

2

Du hast es direkt in Ihrem letzten Satz: Es ist nicht Java oder C#, der schnell ist zu kompilieren, es ist C++, die außergewöhnlich langsam ist, aufgrund seiner komplexen Grammatik und Funktionen zu kompilieren, was am wichtigsten ist templates

2

Wenn Sie denken, javac ist schnell versuchen Sie Jikes .... (siehe http://jikes.sourceforge.net/) Es ist ein Java-Compiler in C++ geschrieben. Leider haben sie nicht mit den neuesten Java Compiler Spezifikationen Schritt gehalten, aber wenn Sie schnell sehen wollen, ist dies das Richtige.

Tony

+0

Danke, ich werde es überprüfen. – Lawand

5

Es gibt ein paar Dinge, die den C++ Compiler langsamer als die von Java/C# machen. Die Grammatik ist viel komplexer, die generische Programmierunterstützung ist in C++ viel leistungsfähiger, aber gleichzeitig ist die Kompilierung teurer. Die Aufnahme von Dateien funktioniert anders als der Import von Modulen.

Inclussion von Header-Dateien

Zuerst, wenn Sie eine Datei in C++, den Inhalt der Datei enthalten (.h in der Regel) in der aktuellen Übersetzungseinheit injiziert werden (einschließlich Wache derselben Header zweimal vermeiden Reinjezierung) und das ist transitiv. Das heißt, wenn Sie Header a.h einschließen, der wiederum b.h enthält, fügt Ihre Kompilierungseinheit den gesamten Code in a ein.h und alle Code in b.h.

Java (oder C#, ich werde über Java sprechen, aber sie sind in dieser ähnlich) haben keine Include-Dateien, sie hängen von den Binaries aus der Kompilation der verwendeten Klassen ab. Das bedeutet, dass Sie beim Kompilieren von a.java, das ein in b.java definiertes Objekt B verwendet, nur die binäre b.class-Klasse überprüfen. Sie müssen nicht tiefer gehen, um die Abhängigkeiten von B zu überprüfen, damit der Prozess früher beendet werden kann (mit nur einer Überprüfungsebene).

Gleichzeitig enthält das Einschließen von Dateien nur die Sprachdefinitionen und die Verarbeitung benötigt Zeit. Wenn der Java/C# -Compiler eine Binärdatei liest, hat er die gleiche Information, wird aber bereits vom Kompilierungsschritt verarbeitet, der ihn generiert hat.

Also am Ende, in C/C++ mehr Dateien enthalten sind und zur gleichen Zeit ist die Verarbeitung dieser Includes teurer als die Verarbeitung von binären Modulen.

Vorlagen

Vorlagen sind speziell auf ihre eigene Weise. Sie können vorkompiliert werden, aber sie sind normalerweise nicht (aus einer guten Reihe von Gründen). Dies bedeutet, dass in allen Kompilierungseinheiten, die std :: vector verwenden, die gesamte Menge der verwendeten Vektormethoden (nicht verwendete Template-Methoden werden nicht kompiliert) verarbeitet und der vom Compiler erzeugte Binärcode verarbeitet wird. In einem späteren Schritt werden während der Verknüpfung redundante Definitionen der gleichen Methode gelöscht, aber während der Kompilierung müssen sie verarbeitet werden.

Die Unterstützung in Java für Generika ist in vielerlei Hinsicht begrenzter. Am Ende gibt es zum Beispiel nur eine Vector-Klassen-Binärdatei, und wenn der Compiler Vector in Java sieht, generiert er Code-Prüfcode, bevor er an die echte Vector-Implementierung delegiert (die Plain-Objekte speichert), und das ist nicht generisch. Der Compiler stellt zwar die Typgarantien bereit, kompiliert jedoch für jeden Typ keinen Vektor.

In C# ist es wieder einmal anders. Die C# Unterstützung für Generics ist komplexer als die von Java, und am Ende unterscheiden sich generische Klassen von einfachen Klassen, aber sie werden nur einmal kompiliert, da das binäre Format alle erforderlichen Informationen enthält.

3

Weil sie etwas ganz anderes machen, produziert der C++ - Compiler optimierten nativen Code, während C#, VB .Net und Java-Compiler eine Intermediate-Sprache erzeugen, als wenn Sie die Anwendung zuerst in nativen Code umwandeln, und deshalb werden Sie langsam Laden der Anwendung in Java usw. beim ersten Ausführen der Anwendung.

Der C++ - Compiler muss die vollständige Optimierung vornehmen, bei der die JITed-Sprachen beim Ausführen der Anwendung optimiert werden.

Jemand würde argumentieren, dass Sie C++ compile time = Java kompilieren Zeit + Zeit für JITing das erste Mal, wenn Sie die Anwendung laden, wenn Sie richtig sein wollen, messen, aber ich denke nicht, dass wäre richtig und fair weil Sie vergleichen Muttersprachen mit JITed oder auch Orangen mit Äpfeln.

+0

C# kompilieren + ngen = C++ kompilieren. Ngen ist schnell. – erikkallen

1

Es ist ein bisschen schwierig, Bytecode-Sprachen wie Java mit nativ kompilierten Sprachen wie C++ zu vergleichen. Ein besserer Vergleich ist Delphi vs C++, wo Delphi viel schneller zu kompilieren ist. Da dies nichts mit Optimierung oder Byte-Code zu tun hat, muss es auf Unterschiede in der Sprachsyntax und der relativen Performance von Includes gegenüber Modulen/Einheiten zurückzuführen sein.

0

Ist der Java-Compiler schnell?

Die Java-zu-Klasse-Übersetzung soll blendend schnell sein, da es nur eine glorifizierte Zip mit einigen Syntaxprüfung ist, so dass im Vergleich zu einem echten Compiler, der Optimierung und Objektcode die "Übersetzung" von Java zu Klasse ist trivial.

Haben Sie einen Vergleich mit dem relativ kleinen Programm "Hallo Welt" und -vergleich mit GCC (C/C++/Ada) und festgestellt, dass Javaac war 30 mal langsamer, und es wurde noch schlimmer in der Laufzeit?