You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2021/03/06 20:40:37 UTC
[groovy] branch GROOVY-9964 updated (3f9f753 -> 281456c)
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a change to branch GROOVY-9964
in repository https://gitbox.apache.org/repos/asf/groovy.git.
discard 3f9f753 GROOVY-9964: Parallelize parsing
new 281456c GROOVY-9964: Parallelize parsing
This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version. This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:
* -- * -- B -- O -- O -- O (3f9f753)
\
N -- N -- N refs/heads/GROOVY-9964 (281456c)
You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.
Any revisions marked "omit" are not gone; other references still
refer to them. Any revisions marked "discard" are gone forever.
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
src/main/java/org/codehaus/groovy/ast/ModuleNode.java | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
[groovy] 01/01: GROOVY-9964: Parallelize parsing
Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch GROOVY-9964
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 281456cdb3cb9cda7908c223d0ae5ef2e2b11373
Author: Daniel Sun <su...@apache.org>
AuthorDate: Sun Mar 7 04:36:13 2021 +0800
GROOVY-9964: Parallelize parsing
---
.../groovy/parser/antlr4/Antlr4ParserPlugin.java | 81 ++++++++++++++++++++--
.../apache/groovy/parser/antlr4/AstBuilder.java | 22 +++---
.../java/org/codehaus/groovy/ast/ModuleNode.java | 4 ++
3 files changed, 90 insertions(+), 17 deletions(-)
diff --git a/src/main/java/org/apache/groovy/parser/antlr4/Antlr4ParserPlugin.java b/src/main/java/org/apache/groovy/parser/antlr4/Antlr4ParserPlugin.java
index 819165e..562b06e 100644
--- a/src/main/java/org/apache/groovy/parser/antlr4/Antlr4ParserPlugin.java
+++ b/src/main/java/org/apache/groovy/parser/antlr4/Antlr4ParserPlugin.java
@@ -18,8 +18,11 @@
*/
package org.apache.groovy.parser.antlr4;
+import groovy.lang.GroovyRuntimeException;
import org.codehaus.groovy.GroovyBugError;
import org.codehaus.groovy.ast.ModuleNode;
+import org.codehaus.groovy.control.CompilationFailedException;
+import org.codehaus.groovy.control.ErrorCollector;
import org.codehaus.groovy.control.ParserPlugin;
import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.control.io.StringReaderSource;
@@ -28,6 +31,12 @@ import org.codehaus.groovy.syntax.Reduction;
import java.io.IOException;
import java.io.Reader;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
/**
* A parser plugin for the new parser.
@@ -49,12 +58,74 @@ public class Antlr4ParserPlugin implements ParserPlugin {
return null;
}
+ private static final ExecutorService THREAD_POOL = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(), new ThreadFactory() {
+ private int seq = 0;
+ @Override
+ public Thread newThread(Runnable r) {
+ Thread t = new Thread(r, "parser-thread-" + seq++);
+ t.setDaemon(true);
+ return t;
+ }
+ });
+
@Override
public ModuleNode buildAST(final SourceUnit sourceUnit, final ClassLoader classLoader, final Reduction cst) {
- AstBuilder builder = new AstBuilder(sourceUnit,
- sourceUnit.getConfiguration().isGroovydocEnabled(),
- sourceUnit.getConfiguration().isRuntimeGroovydocEnabled()
- );
- return builder.buildAST();
+ CountDownLatch countDownLatch = new CountDownLatch(1);
+ AtomicReference<ModuleNode> moduleNodeAtomicReference = new AtomicReference<>();
+ ExceptionHolder<CompilationFailedException> exceptionHolder = new ExceptionHolder<>(countDownLatch);
+ submitParseTask(sourceUnit, countDownLatch, moduleNodeAtomicReference, exceptionHolder, "LL");
+ submitParseTask(sourceUnit, countDownLatch, moduleNodeAtomicReference, exceptionHolder, "SLL");
+
+ ModuleNode moduleNode;
+ try {
+ countDownLatch.await();
+ moduleNode = moduleNodeAtomicReference.get();
+ } catch (InterruptedException e) {
+ throw new GroovyRuntimeException(e);
+ }
+
+ if (null != moduleNode) {
+ moduleNode.setContext(sourceUnit);
+ return moduleNode;
+ }
+ throw exceptionHolder.get();
+ }
+
+ private void submitParseTask(SourceUnit sourceUnit, CountDownLatch countDownLatch, AtomicReference<ModuleNode> moduleNodeAtomicReference, ExceptionHolder<CompilationFailedException> exceptionHolder, String predictionModeName) {
+ THREAD_POOL.submit(() -> {
+ SourceUnit su = new SourceUnit(sourceUnit.getName(), sourceUnit.getSource(), sourceUnit.getConfiguration(), sourceUnit.getClassLoader(), new ErrorCollector(sourceUnit.getConfiguration()));
+ AstBuilder builder = new AstBuilder(su,
+ su.getConfiguration().isGroovydocEnabled(),
+ su.getConfiguration().isRuntimeGroovydocEnabled()
+ );
+
+ try {
+ moduleNodeAtomicReference.set(builder.buildAST(predictionModeName));
+ countDownLatch.countDown();
+ } catch (CompilationFailedException ex) {
+ exceptionHolder.set(ex);
+ }
+ });
+ }
+
+ private static class ExceptionHolder<T extends Exception> {
+ private final AtomicReference<T> ar = new AtomicReference<>();
+ private final AtomicInteger count = new AtomicInteger(0);
+ private final CountDownLatch countDownLatch;
+
+ private ExceptionHolder(CountDownLatch countDownLatch) {
+ this.countDownLatch = countDownLatch;
+ }
+
+ public final void set(T compilationFailedException) {
+ ar.set(compilationFailedException);
+ if (2 == count.incrementAndGet()) {
+ countDownLatch.countDown();
+ }
+ }
+
+ public T get() {
+ return ar.get();
+ }
}
}
diff --git a/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java b/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
index 669be8a..720e6fa 100644
--- a/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
+++ b/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
@@ -371,21 +371,19 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> {
return charStream;
}
- private GroovyParserRuleContext buildCST() throws CompilationFailedException {
+ private GroovyParserRuleContext buildCST(final String predictionModeName) throws CompilationFailedException {
GroovyParserRuleContext result;
try {
// parsing have to wait util clearing is complete.
AtnManager.READ_LOCK.lock();
try {
- result = buildCST(PredictionMode.SLL);
- } catch (Throwable t) {
- // if some syntax error occurred in the lexer, no need to retry the powerful LL mode
- if (t instanceof GroovySyntaxError && GroovySyntaxError.LEXER == ((GroovySyntaxError) t).getSource()) {
- throw t;
+ PredictionMode predictionMode = PredictionMode.valueOf(predictionModeName);
+ if (PredictionMode.SLL == predictionMode) {
+ result = doBuildCST(PredictionMode.SLL);
+ } else {
+ result = doBuildCST(PredictionMode.LL);
}
-
- result = buildCST(PredictionMode.LL);
} finally {
AtnManager.READ_LOCK.unlock();
}
@@ -396,10 +394,10 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> {
return result;
}
- private GroovyParserRuleContext buildCST(final PredictionMode predictionMode) {
+ private GroovyParserRuleContext doBuildCST(final PredictionMode predictionMode) {
parser.getInterpreter().setPredictionMode(predictionMode);
- if (PredictionMode.SLL.equals(predictionMode)) {
+ if (PredictionMode.SLL == predictionMode) {
this.removeErrorListeners();
} else {
parser.getInputStream().seek(0);
@@ -423,9 +421,9 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> {
return cfe;
}
- public ModuleNode buildAST() {
+ public ModuleNode buildAST(final String predictionModeName) {
try {
- return (ModuleNode) this.visit(this.buildCST());
+ return (ModuleNode) this.visit(this.buildCST(predictionModeName));
} catch (Throwable t) {
throw convertException(t);
}
diff --git a/src/main/java/org/codehaus/groovy/ast/ModuleNode.java b/src/main/java/org/codehaus/groovy/ast/ModuleNode.java
index fedec5a..fb9c1a9 100644
--- a/src/main/java/org/codehaus/groovy/ast/ModuleNode.java
+++ b/src/main/java/org/codehaus/groovy/ast/ModuleNode.java
@@ -508,4 +508,8 @@ public class ModuleNode extends ASTNode {
public BlockStatement getStatementBlock() {
return statementBlock;
}
+
+ public void setContext(SourceUnit sourceUnit) {
+ this.context = sourceUnit;
+ }
}