Skip to content

Commit 36a6581

Browse files
EcljpseB0Tiloveeclipse
authored andcommitted
[performance] BatchImageBuilder: write .class files in batches
ProcessTaskManager * use java.util.concurrent for queue * signal Cancel/Exception/Stop via the queue * implements AutoCloseable for try-with-resource * drain as much Elements as possible from the queue Improves the performance of "Clean all projects" For example building platform workspace on Windows AbstractImageBuilder.compile(): 120 sec -> 80 sec With this change the Compiler is actually waiting for parsing most time and not for the write to FileSystem anymore.
1 parent 8465271 commit 36a6581

File tree

7 files changed

+284
-200
lines changed

7 files changed

+284
-200
lines changed

org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/Compiler.java

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,6 @@ protected void restoreAptProblems() {
553553

554554
protected void processCompiledUnits(int startingIndex, boolean lastRound) throws java.lang.Error {
555555
CompilationUnitDeclaration unit = null;
556-
ProcessTaskManager processingTask = null;
557556
try {
558557
if (this.useSingleThread) {
559558
// process all units (some more could be injected in the loop by the lookup environment)
@@ -596,30 +595,37 @@ protected void processCompiledUnits(int startingIndex, boolean lastRound) throws
596595
}));
597596
}
598597
} else {
599-
processingTask = new ProcessTaskManager(this, startingIndex);
600-
int acceptedCount = 0;
601-
// process all units (some more could be injected in the loop by the lookup environment)
602-
// the processTask can continue to process units until its fixed sized cache is full then it must wait
603-
// for this this thread to accept the units as they appear (it only waits if no units are available)
604-
while (true) {
598+
try (ProcessTaskManager processingTask = new ProcessTaskManager(this, startingIndex)){
599+
int acceptedCount = 0;
600+
// process all units (some more could be injected in the loop by the lookup environment)
601+
// the processTask can continue to process units until its fixed sized cache is full then it must wait
602+
// for this this thread to accept the units as they appear (it only waits if no units are available)
603+
this.requestor.startBatch();
605604
try {
606-
unit = processingTask.removeNextUnit(); // waits if no units are in the processed queue
607-
} catch (Error | RuntimeException e) {
608-
unit = processingTask.unitToProcess;
609-
throw e;
605+
Collection<CompilationUnitDeclaration> units;
606+
do {
607+
try {
608+
units = processingTask.removeNextUnits();
609+
} catch (Error | RuntimeException e) {
610+
unit = processingTask.getUnitWithError();
611+
throw e;
612+
}
613+
for (CompilationUnitDeclaration u : units) {
614+
unit = u;
615+
reportWorked(1, acceptedCount++);
616+
this.stats.lineCount += unit.compilationResult.lineSeparatorPositions.length;
617+
this.requestor.acceptResult(unit.compilationResult.tagAsAccepted());
618+
if (this.options.verbose)
619+
this.out.println(Messages.bind(Messages.compilation_done,
620+
new String[] { String.valueOf(acceptedCount),
621+
String.valueOf(this.totalUnits), new String(unit.getFileName()) }));
622+
}
623+
// processingTask had no more units available => use the time to flush:
624+
this.requestor.flushBatch();
625+
} while (!units.isEmpty());
626+
} finally {
627+
this.requestor.endBatch();
610628
}
611-
if (unit == null) break;
612-
reportWorked(1, acceptedCount++);
613-
this.stats.lineCount += unit.compilationResult.lineSeparatorPositions.length;
614-
this.requestor.acceptResult(unit.compilationResult.tagAsAccepted());
615-
if (this.options.verbose)
616-
this.out.println(
617-
Messages.bind(Messages.compilation_done,
618-
new String[] {
619-
String.valueOf(acceptedCount),
620-
String.valueOf(this.totalUnits),
621-
new String(unit.getFileName())
622-
}));
623629
}
624630
}
625631
if (!lastRound) {
@@ -640,10 +646,6 @@ protected void processCompiledUnits(int startingIndex, boolean lastRound) throws
640646
this.handleInternalException(e, unit, null);
641647
throw e; // rethrow
642648
} finally {
643-
if (processingTask != null) {
644-
processingTask.shutdown();
645-
processingTask = null;
646-
}
647649
reset();
648650
this.annotationProcessorStartIndex = 0;
649651
this.stats.endTime = System.currentTimeMillis();

org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ICompilerRequestor.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,26 @@ public interface ICompilerRequestor {
2222
* Accept a compilation result.
2323
*/
2424
public void acceptResult(CompilationResult result);
25+
26+
/**
27+
* Optionally called to start multiple {@link #acceptResult(CompilationResult)}
28+
*/
29+
public default void startBatch() {
30+
//nothing
31+
}
32+
33+
/**
34+
* Optionally called after some {@link #acceptResult(CompilationResult)} to signal a good point in time
35+
*/
36+
public default void flushBatch() {
37+
//nothing
38+
}
39+
40+
/**
41+
* if {@link #startBatch} was called then endBatch is called to finalize possibly multiple
42+
* {@link #acceptResult(CompilationResult)}
43+
*/
44+
public default void endBatch() {
45+
// nothing
46+
}
2547
}

0 commit comments

Comments
 (0)