From d3d92be049ba5ed06b6ae35fca0161fe32bbca68 Mon Sep 17 00:00:00 2001 From: Martin Kouba Date: Tue, 17 Sep 2024 10:15:09 +0200 Subject: [PATCH] Qute: IfSectionHelper - improve performance for common use case --- .../java/io/quarkus/qute/IfSectionHelper.java | 93 ++++++++++++++++++- 1 file changed, 90 insertions(+), 3 deletions(-) diff --git a/independent-projects/qute/core/src/main/java/io/quarkus/qute/IfSectionHelper.java b/independent-projects/qute/core/src/main/java/io/quarkus/qute/IfSectionHelper.java index 6d7f7bdf8d055..48e2ae24dee02 100644 --- a/independent-projects/qute/core/src/main/java/io/quarkus/qute/IfSectionHelper.java +++ b/independent-projects/qute/core/src/main/java/io/quarkus/qute/IfSectionHelper.java @@ -246,7 +246,12 @@ static class OperandCondition implements Condition { @Override public CompletionStage evaluate(SectionResolutionContext context) { - CompletionStage ret = context.resolutionContext().evaluate(expression); + CompletionStage ret; + if (expression.isLiteral()) { + ret = expression.asLiteral(); + } else { + ret = context.resolutionContext().evaluate(expression); + } if (operator == Operator.NOT) { return ret.thenApply(this::logicalComplement); } @@ -270,6 +275,86 @@ public String toString() { } + static class DoubletonCondition implements Condition { + + final Condition condition1; + final Condition condition2; + final Operator operator; + + private DoubletonCondition(Condition condition1, Condition condition2, Operator operator) { + this.condition1 = Objects.requireNonNull(condition1); + this.condition2 = Objects.requireNonNull(condition2); + this.operator = operator; + } + + @Override + public CompletionStage evaluate(SectionResolutionContext context) { + CompletionStage ret = condition1.evaluate(context); + if (ret instanceof CompletedStage completed) { + ret = evaluateSecond(context, completed.get()); + } else { + ret = ret.thenCompose(first -> evaluateSecond(context, first)); + } + if (operator == Operator.NOT) { + return ret.thenApply(this::logicalComplement); + } + return ret; + } + + @Override + public Operator getOperator() { + return operator; + } + + @Override + public String toString() { + return "DoubletonCondition [condition1=" + condition1 + ", condition2=" + condition2 + ", operator=" + operator + + "]"; + } + + CompletionStage evaluateSecond(SectionResolutionContext context, Object firstVal) { + Boolean shortResult = null; + Operator operator = condition2.getOperator(); + if (operator != null && operator.isShortCircuiting()) { + shortResult = operator.evaluate(firstVal); + } + if (shortResult != null) { + // There is no need to continue with the next operand + return CompletedStage.of(shortResult); + } + CompletionStage second = condition2.evaluate(context); + if (second instanceof CompletedStage completed) { + return processValues(operator, firstVal, completed.get()); + } else { + return second.thenCompose(c2 -> processValues(operator, firstVal, c2)); + } + } + + CompletionStage processValues(Operator operator, + Object firstVal, Object secondVal) { + Object val; + if (operator == null || !operator.isBinary()) { + val = secondVal; + } else { + // Binary operator + try { + if (Results.isNotFound(secondVal)) { + secondVal = null; + } + Object localValue = firstVal; + if (Results.isNotFound(localValue)) { + localValue = null; + } + val = operator.evaluate(localValue, secondVal); + } catch (Throwable e) { + return CompletedStage.failure(e); + } + } + return CompletedStage.of(val); + } + + } + static class CompositeCondition implements Condition { final List conditions; @@ -310,8 +395,8 @@ CompletionStage evaluateNext(SectionResolutionContext context, Object pr return processConditionValue(context, operator, previousValue, literalVal, iter); } else { CompletionStage ret = next.evaluate(context); - if (ret instanceof CompletedStage) { - return processConditionValue(context, operator, previousValue, ((CompletedStage) ret).get(), + if (ret instanceof CompletedStage completed) { + return processConditionValue(context, operator, previousValue, completed.get(), iter); } else { return ret.thenCompose(r -> processConditionValue(context, operator, previousValue, r, iter)); @@ -664,6 +749,8 @@ static Condition createCondition(Object param, SectionBlock block, Operator oper if (operator == null && conditions.size() == 1) { condition = conditions.get(0); + } else if (conditions.size() == 2) { + condition = new DoubletonCondition(conditions.get(0), conditions.get(1), operator); } else { condition = new CompositeCondition(operator, ImmutableList.copyOf(conditions)); }