Warum läuft javac 1.5 so langsam, verglichen mit dem Eclipse-Compiler?

8

Ich habe ein Java Maven Projekt mit ungefähr 800 Quelldateien (einige davon wurden von javacc / JTB generiert), was gut 25 Minuten dauert, um mit javac zu kompilieren.

Wenn ich meine pom.xml-Datei geändert habe, um den Eclipse-Compiler zu verwenden, dauert das Kompilieren etwa 30 Sekunden.

Irgendwelche Vorschläge, warum javac (1.5) so langsam läuft? (Ich möchte nicht permanent zum Eclipse-Compiler wechseln, da das Plugin für Maven mehr als ein kleiner Buggy zu sein scheint.)

Ich habe einen Testfall, der das Problem leicht reproduziert. Der folgende Code generiert eine Anzahl von Quelldateien im Standardpaket. Wenn Sie versuchen, ImplementingClass.java mit javac zu kompilieren, wird es scheinbar unangemessen lange pausieren.

%Vor%     
Simon Nickerson 26.03.2009, 16:32
quelle

8 Antworten

6

Sie erhalten das gleiche Verhalten mit JDK 1.6, einschließlich Update 14, Build 04, mit G1 ändert sich das Verhalten nicht (obwohl G1 scheint wirklich gut zu funktionieren).

Überwachung von javac mit jvisualvm, wiederholte Thread Dumps zeigen den Hauptthread viel Zeit in

%Vor%

und durch eine große Anzahl von kurzlebigen Instanzen dieser Klassen:

%Vor%

Ich vermute, dass der Code durch com.sun.tools.javac.comp.Check.checkCompatibleConcretes wackelt, indem er jede Methode mit jeder anderen Methode vergleicht

Die Javadoc-Methode dieser Methode:

%Vor%

Es kann sein, dass der Compiler von eclipse diese Überprüfung nicht durchführt oder nicht auf die gleiche Weise durchführt.

    
Stephen Denne 08.04.2009, 03:53
quelle
7

Sun hat mir per E-Mail bestätigt, dass dies ein neuer Fehler ist ( 6827648 ) Fehlerdatenbank).

    
Simon Nickerson 08.04.2009 12:03
quelle
5

Es kann sein, dass der javac-Compiler nahe bei seinem Heap-Limit arbeitet (64MB oder so). In diesem Fall verbringt es die meiste Zeit im Garbage Collector. Geben Sie dem Compiler ein gutes Stück Speicher, sagen Sie 256M oder 512M und sehen Sie, ob es schneller läuft.

    
Ingo 03.04.2009 14:48
quelle
2

Die Tatsache, dass Sie die generierte Quelle, den massiven Geschwindigkeitsunterschied und StackOverflowError verwenden, könnte darauf hindeuten, dass eine (oder mehrere) Ihrer Dateien einige Konstrukte enthält, die der javac parsert stimmt damit nicht überein.

Könnten Sie versuchen, nur Teilmengen Ihres Codes zu kompilieren und zu sehen, ob eine Klasse / Paket den Prozess besonders verlangsamt (wahrscheinlich einer der generierten).

    
Joachim Sauer 27.03.2009 08:44
quelle
1

Für den Sun-Compiler starten Sie einen ganzen JVM-Prozess für jede Datei, die Sie kompilieren möchten. Für den Eclipse-Compiler wird nur eine Verbindung zu einem Daemon-Prozess hergestellt. Ich schlage vor, fork auf false zu setzen, obwohl es immer noch nicht ganz so schnell sein kann.

    
Tom Hawtin - tackline 26.03.2009 17:19
quelle
0

Vielleicht kompiliert der Eclipse-Build nur die modifizierte Quelle. Was passiert, wenn Sie es nach einem Clean in Eclipse kompilieren?

    
Jack BeNimble 26.03.2009 16:42
quelle
0

Ich weiß nicht, wie Maven den Compiler aufruft, aber die von Ihnen erwähnten Performance-Zahlen legen nahe, dass javac in seinem eigenen Prozess / VM ausgeführt wird, wie bereits in einer anderen Antwort vorgeschlagen. Da das Starten eines neuen Prozesses / VM für jede Datei, die Sie kompilieren, sehr kostspielig ist, müssen Sie sicherstellen, dass der Compiler so konfiguriert ist, dass er die VM verwendet, die Sie möglicherweise bereits haben. Ich weiß, dass ANT das anbietet, aber ich habe selbst keine Maven benutzt. Angesichts der Tatsache, dass es beliebt ist, bezweifle ich, dass es so ein wichtiges Merkmal fehlt.

    
lothar 03.04.2009 20:05
quelle
0

Ich denke, es läuft so etwas wie das folgende: Maven gabs javac, JVM-Prozesse für separate Schritte in seinem Lebenszyklus: Maven Build Lebenszyklus

Normalerweise führt Eclipse seine Kompilierung im Hintergrund (bei Save) durch, sodass dieser Schritt der Kompilierungsphase hinzugefügt wird. Wenn es erhebliche Abhängigkeiten gibt, verlieren Sie hier den Durchsatz.

Zusätzlich (abhängig von der mvn-Konfiguration) erhält jede Testmethode ihre eigene JVM. Da die Testdurchführung eine Voraussetzung für die Paketphase ist, ist es möglich, dass Sie Zeit für Ihre JUnit-Testdurchführung verlieren (insbesondere wenn es sich um langsame Tests handelt). Dies ist wahrscheinlich nur dann der Fall, wenn Sie in Ihrem Quellcode viel Testcode haben.

Am wahrscheinlichsten ist, dass Ihre Klasse erhebliche Mengen an Datei-I / O-Operationen durchführt. Es sieht so aus, als ob Ihre Schleife 1000 Mal pro Dateierkennungsereignis ausgeführt wird, was 800 * 1000 = 800.000 PrintStream-Kreationen im Schleifenkörper bedeutet.

    
jasonnerothin 06.04.2009 18:08
quelle

Tags und Links