Skip to content

Commit

Permalink
Qute: improve TemplateNode/ResultNode processing
Browse files Browse the repository at this point in the history
Co-authored-by: Francesco Nigro <[email protected]>
  • Loading branch information
franz1981 authored and mkouba committed Sep 4, 2024
1 parent c4c9c1a commit 09be8e6
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,21 @@ public static CompletionStage<Object> notFound() {
return CompletedStage.of(NotFound.EMPTY);
}

static CompletionStage<ResultNode> process(List<CompletionStage<ResultNode>> results) {
// Collect async results first
static CompletionStage<ResultNode> resolveAndProcess(List<TemplateNode> nodes, ResolutionContext context) {
int nodesCount = nodes.size();
if (nodesCount == 1) {
// Single node in the block
return resolveWith(nodes.get(0), context);
}
@SuppressWarnings("unchecked")
Supplier<ResultNode>[] allResults = new Supplier[results.size()];
Supplier<ResultNode>[] allResults = new Supplier[nodesCount];
List<CompletableFuture<ResultNode>> asyncResults = null;
int idx = 0;
for (CompletionStage<ResultNode> result : results) {
for (TemplateNode templateNode : nodes) {
final CompletionStage<ResultNode> result = resolveWith(templateNode, context);
if (result instanceof CompletedStage) {
allResults[idx++] = (CompletedStage<ResultNode>) result;
// No async computation needed
continue;
allResults[idx++] = (CompletedStage<ResultNode>) result;
} else {
CompletableFuture<ResultNode> fu = result.toCompletableFuture();
if (asyncResults == null) {
Expand All @@ -63,6 +67,11 @@ static CompletionStage<ResultNode> process(List<CompletionStage<ResultNode>> res
allResults[idx++] = Futures.toSupplier(fu);
}
}
return toCompletionStage(allResults, asyncResults);
}

private static CompletionStage<ResultNode> toCompletionStage(Supplier<ResultNode>[] allResults,
List<CompletableFuture<ResultNode>> asyncResults) {
if (asyncResults == null) {
// No async results present
return CompletedStage.of(new MultiResultNode(allResults));
Expand All @@ -86,6 +95,48 @@ static CompletionStage<ResultNode> process(List<CompletionStage<ResultNode>> res
}
}

/**
* This method is trying to speed-up the resolve method which could become a virtual dispatch, harming
* the performance of trivial implementations like TextNode::resolve, which is as simple as a field access.
*/
private static CompletionStage<ResultNode> resolveWith(TemplateNode templateNode, ResolutionContext context) {
if (templateNode instanceof TextNode textNode) {
return textNode.resolve(context);
}
if (templateNode instanceof ExpressionNode expressionNode) {
return expressionNode.resolve(context);
}
if (templateNode instanceof SectionNode sectionNode) {
return sectionNode.resolve(context);
}
if (templateNode instanceof ParameterDeclarationNode paramNode) {
return paramNode.resolve(context);
}
return templateNode.resolve(context);
}

static CompletionStage<ResultNode> process(List<CompletionStage<ResultNode>> results) {
// Collect async results first
@SuppressWarnings("unchecked")
Supplier<ResultNode>[] allResults = new Supplier[results.size()];
List<CompletableFuture<ResultNode>> asyncResults = null;
int idx = 0;
for (CompletionStage<ResultNode> result : results) {
if (result instanceof CompletedStage) {
// No async computation needed
allResults[idx++] = (CompletedStage<ResultNode>) result;
} else {
CompletableFuture<ResultNode> fu = result.toCompletableFuture();
if (asyncResults == null) {
asyncResults = new ArrayList<>();
}
asyncResults.add(fu);
allResults[idx++] = Futures.toSupplier(fu);
}
}
return toCompletionStage(allResults, asyncResults);
}

/**
* Represents a "result not found" value.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,16 +235,7 @@ public CompletionStage<ResultNode> execute(SectionBlock block, ResolutionContext
// Use the main block
block = blocks.get(0);
}
int size = block.nodes.size();
if (size == 1) {
// Single node in the block
return block.nodes.get(0).resolve(context);
}
List<CompletionStage<ResultNode>> results = new ArrayList<>(size);
for (TemplateNode node : block.nodes) {
results.add(node.resolve(context));
}
return Results.process(results);
return Results.resolveAndProcess(block.nodes, context);
}

@Override
Expand Down

0 comments on commit 09be8e6

Please sign in to comment.