2015-06-06 5 views
27
time javac Main.java          --> 0m1.050s 
time javac Main.java & javac Main.java     --> 0m1.808s 
time javac Main.java & javac Main.java & javac Main.java --> 0m2.690s 
time javac Main.java & ... 8 time       --> 0m8.309s 

Wenn wir javac Befehl parallel und mit jeder Erhöhung in javac Befehl ausführen ~1 sec wird für all javac Befehle hinzugefügt abzuschließen.warum die parallele Ausführung auf Java-Kompilierung nimmt lineares Wachstum in Zeit

Warum ist ein lineares Wachstum die Zeit?

Ist alles javac Prozess, während in irgendeiner Art auf locks beteiligt laufen, wenn ja, wie es zu überwinden, um nicht ein lineares Wachstum in der Zeit zu haben


PS: Ich habe oben versucht, auf single core machine, double core machine, 4 core machine zeigten alle dasselbe Verhalten.

PS2: Umwelt RedHat7, javac 1.7.0_79

+2

Konnte leicht I/O-gebunden sein, nicht CPU-gebunden. –

+1

jede Idee, wie zu bestätigen, ob io gebunden ... sieht so aus, weil unsere Daten sehr klein sind – Bhuvan

+0

Hmmm, 'javac' will Dateien. Ich nehme an, Sie könnten eine RAM-Disk verwenden. Ich würde auch sicherstellen, dass "Main.java" ** groß war **, also checkst du wirklich Compilation vs. Load/Save. Die eigentliche Frage ist natürlich: Was wollen Sie optimieren? Denn wenn es der gesamte Prozess ist, ist I/O ein wichtiger Faktor, den Sie nicht testen möchten. –

Antwort

27

Der Java-Compiler bereits behandelt seine Arbeit auf die verfügbaren Prozessoren teilen, selbst wenn nur eine einzelne Datei zu kompilieren. Wenn Sie daher separate Compiler-Instanzen parallel ausführen, erzielen Sie nicht die erwarteten Leistungssteigerungen.

Um dies zu demonstrieren, generierte ich ein großes (1 Million Zeilen, 10.000 Methoden) Java-Programm in einer einzigen Datei namens Main1.java. Dann erstellte zusätzliche Kopien als Main2.java bis Main8.java. Kompilieren Zeiten sind wie folgt:

Einzeldatei der Kompilierung:

time javac Main1.java & --> (real) 11.6 sec 

beobachten diese einzelne Datei in top ergab Prozessorauslastung vor allem in der 200-400% -Bereich kompilieren (was mehrere CPU-Auslastung 100% pro CPU) mit gelegentlichen Spikes im Bereich von 700% (der Maximalwert auf dieser Maschine beträgt 800%, da es 8 Prozessoren gibt).

Als nächstes werden zwei Dateien gleichzeitig:

time javac Main1.java & --> (real) 14.5 sec 
time javac Main2.java & --> (real) 14.8 sec 

es dauerte also nur 14,8 Sekunden zwei zu kompilieren, wenn es 11,6 Sekunden nahm eine zu kompilieren. Das ist definitiv nicht linear. Es war klar, wenn man sich die top anschaute, während diese ausgeführt wurden, dass jeder Java-Compiler nur maximal vier CPUs auf einmal nutzte (mit gelegentlichen höheren Spitzen). Aus diesem Grund liefen die beiden Compiler über acht CPUs, die größtenteils parallel zueinander waren.

Als nächstes vier Dateien gleichzeitig:

time javac Main1.java & --> (real) 24.2 sec 
time javac Main2.java & --> (real) 24.6 sec 
time javac Main3.java & --> (real) 25.0 sec 
time javac Main4.java & --> (real) 25.0 sec 

Okay, hier haben wir gegen die Wand. Wir können den Compiler nicht mehr parallelisieren. Vier Dateien benötigten 25 Sekunden, wenn zwei 14,8 Sekunden benötigten. Es gibt eine kleine Optimierung, aber es ist hauptsächlich eine lineare Zeitsteigerung.

Schließlich acht gleichzeitig:

time javac Main1.java & --> (real) 51.9 sec 
time javac Main2.java & --> (real) 52.3 sec 
time javac Main3.java & --> (real) 52.5 sec 
time javac Main4.java & --> (real) 53.0 sec 
time javac Main5.java & --> (real) 53.4 sec 
time javac Main6.java & --> (real) 53.5 sec 
time javac Main7.java & --> (real) 53.6 sec 
time javac Main8.java & --> (real) 54.6 sec 

Das war eigentlich ein wenig schlechter als linear, wie acht 54,6 Sekunden dauerte, während vier nur 25,0 nahm.

Also denke ich, dass der Glaube daran, dass der Compiler einen anständigen Job machen wird, die Arbeit über die verfügbaren CPU-Ressourcen zu optimieren, und dass der Versuch, zusätzliche Parallelisierung per Hand hinzuzufügen, begrenzt sein wird (falls vorhanden) profitieren.

Edit:

Als Referenz gibt es zwei Einträge ich in Oracle Bug-Datenbank gefunden javac in Bezug auf die Verbesserung Vorteile von mehreren Prozessoren zu nutzen:

  • Bug ID: JDK-6629150 - Die ursprüngliche Beschwerde war dies möglicherweise markiert als ein Duplikat von:
  • Bug ID: JDK-6713663 - Schlägt die Auflösung vor, und basierend auf dem "Resolved Date" scheint, dass Multi-Prozessor-Unterstützung in javac am 2008-06-12 hinzugefügt wurde.
+1

nette Erklärung, aber wenn wir 8 Hallo Welt Java (als Gegenteil zu Ihrer) Datei kompilieren dann parallel mit 8 Javac auf einem 8-Core-Maschine, dann sollte es in 1 sek abgeschlossen haben .... richtig? – Bhuvan

+0

@ user2410148: Mit einer kleinen "Hallo Welt" -Datei habe ich die folgenden Kompilierzeiten: 1 dauerte 0,32 Sekunden; 2 benötigte 0,39 Sekunden; 4 dauerte 0,54 Sekunden; 8 dauerte 1,02 Sekunden. Es scheint dem gleichen Muster zu folgen, wo es in zwei parallelisierte Parallelen zerlegt wurde, okay, aber dann zu versuchen, vier oder acht zu machen, war eine linearere Zunahme der Zeit. Ich denke, das gleiche Konzept gilt auch für den kleinen Maßstab: Lassen Sie den Compiler die Parallelisierung für Sie durchführen. –

+0

Ich glaube nicht, dass deine Schlussfolgerung stichhaltig ist. Um zu beweisen, sollten Sie nicht wissen, wie lange es dauert, 1-8 in Serie zu kompilieren? Ansonsten vergleichen Sie zwei verschiedene Arbeitsmengen. Durch meine Schätzung Ihrer Zahlen kann ich Javac starten und 88 Sekunden warten oder ich kann es von der Kommandozeile aus parallelisieren und 55 Sekunden warten. Die meisten meiner Java-Dateien liegen im Bereich von 500 Zeilen. Ich denke, Javac wird es schwerer haben, mehrere Kerne in kleineren Dateien/Klassen zu verwenden. Ich sage nicht, dass 16000 Paralleljacac die ideale Lösung ist, aber ich stimme dem Rat nicht zu, nur Glauben zu haben. – Ryan