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.
Konnte leicht I/O-gebunden sein, nicht CPU-gebunden. –
jede Idee, wie zu bestätigen, ob io gebunden ... sieht so aus, weil unsere Daten sehr klein sind – Bhuvan
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. –