From 231be41244e89f17d8cfff4b8241da6bb55ac98f Mon Sep 17 00:00:00 2001 From: Rishabh Date: Fri, 3 Nov 2023 11:45:21 +0530 Subject: [PATCH 1/5] Replaced stream with for loop for slightly better performance --- .../appform/hope/core/visitors/Evaluator.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/hope-core/src/main/java/io/appform/hope/core/visitors/Evaluator.java b/hope-core/src/main/java/io/appform/hope/core/visitors/Evaluator.java index 70f5942..539f1a8 100644 --- a/hope-core/src/main/java/io/appform/hope/core/visitors/Evaluator.java +++ b/hope-core/src/main/java/io/appform/hope/core/visitors/Evaluator.java @@ -72,18 +72,24 @@ public List evaluate( final List evaluatables, final JsonNode node) { val logicEvaluator = new LogicEvaluator(new EvaluationContext(parseContext.parse(node), node, this)); - return evaluatables.stream() - .map(evaluatable -> evaluatable.accept(logicEvaluator)) - .collect(Collectors.toList()); + List list = new ArrayList<>(); + for (Evaluatable evaluatable : evaluatables) { + list.add(evaluatable.accept(logicEvaluator)); + } + return list; } public OptionalInt evaluateFirst( final List rules, final JsonNode node) { val logicEvaluator = new LogicEvaluator(new EvaluationContext(parseContext.parse(node), node, this)); - return IntStream.range(0, rules.size()) - .filter(index -> rules.get(index).accept(logicEvaluator)) - .findFirst(); + int bound = rules.size(); + for (int index = 0; index < bound; index++) { + if (rules.get(index).accept(logicEvaluator)) { + return OptionalInt.of(index); + } + } + return OptionalInt.empty(); } @Data From ea7389cde78075f763d320a830619ebfb4c8b174 Mon Sep 17 00:00:00 2001 From: Rishabh Date: Mon, 6 Nov 2023 14:03:44 +0530 Subject: [PATCH 2/5] Creating baseline --- .../appform/hope/core/visitors/Evaluator.java | 18 ++++++------------ ...ope.lang.JsonPathPerfTest.testBulkEval.json | 6 +++--- ...e.lang.JsonPathPerfTest.testSingleEval.json | 6 +++--- .../io/appform/hope/lang/BenchmarkTest.java | 4 ++-- 4 files changed, 14 insertions(+), 20 deletions(-) diff --git a/hope-core/src/main/java/io/appform/hope/core/visitors/Evaluator.java b/hope-core/src/main/java/io/appform/hope/core/visitors/Evaluator.java index 539f1a8..70f5942 100644 --- a/hope-core/src/main/java/io/appform/hope/core/visitors/Evaluator.java +++ b/hope-core/src/main/java/io/appform/hope/core/visitors/Evaluator.java @@ -72,24 +72,18 @@ public List evaluate( final List evaluatables, final JsonNode node) { val logicEvaluator = new LogicEvaluator(new EvaluationContext(parseContext.parse(node), node, this)); - List list = new ArrayList<>(); - for (Evaluatable evaluatable : evaluatables) { - list.add(evaluatable.accept(logicEvaluator)); - } - return list; + return evaluatables.stream() + .map(evaluatable -> evaluatable.accept(logicEvaluator)) + .collect(Collectors.toList()); } public OptionalInt evaluateFirst( final List rules, final JsonNode node) { val logicEvaluator = new LogicEvaluator(new EvaluationContext(parseContext.parse(node), node, this)); - int bound = rules.size(); - for (int index = 0; index < bound; index++) { - if (rules.get(index).accept(logicEvaluator)) { - return OptionalInt.of(index); - } - } - return OptionalInt.empty(); + return IntStream.range(0, rules.size()) + .filter(index -> rules.get(index).accept(logicEvaluator)) + .findFirst(); } @Data diff --git a/hope-lang/perf/results/io.appform.hope.lang.JsonPathPerfTest.testBulkEval.json b/hope-lang/perf/results/io.appform.hope.lang.JsonPathPerfTest.testBulkEval.json index 2ac9e8c..526b492 100644 --- a/hope-lang/perf/results/io.appform.hope.lang.JsonPathPerfTest.testBulkEval.json +++ b/hope-lang/perf/results/io.appform.hope.lang.JsonPathPerfTest.testBulkEval.json @@ -1,8 +1,8 @@ { "name" : "io.appform.hope.lang.JsonPathPerfTest.testBulkEval", "mode" : "Throughput", - "iterations" : 2, + "iterations" : 3, "threads" : 1, - "forks" : 3, - "mean_ops" : 44851.40995773682 + "forks" : 2, + "mean_ops" : 98359.40086170378 } \ No newline at end of file diff --git a/hope-lang/perf/results/io.appform.hope.lang.JsonPathPerfTest.testSingleEval.json b/hope-lang/perf/results/io.appform.hope.lang.JsonPathPerfTest.testSingleEval.json index 7d79f03..5667af1 100644 --- a/hope-lang/perf/results/io.appform.hope.lang.JsonPathPerfTest.testSingleEval.json +++ b/hope-lang/perf/results/io.appform.hope.lang.JsonPathPerfTest.testSingleEval.json @@ -1,8 +1,8 @@ { "name" : "io.appform.hope.lang.JsonPathPerfTest.testSingleEval", "mode" : "Throughput", - "iterations" : 2, + "iterations" : 3, "threads" : 1, - "forks" : 3, - "mean_ops" : 5292.365475932045 + "forks" : 2, + "mean_ops" : 12628.986025477061 } \ No newline at end of file diff --git a/hope-lang/src/test/java/io/appform/hope/lang/BenchmarkTest.java b/hope-lang/src/test/java/io/appform/hope/lang/BenchmarkTest.java index 1c99deb..a8e3007 100644 --- a/hope-lang/src/test/java/io/appform/hope/lang/BenchmarkTest.java +++ b/hope-lang/src/test/java/io/appform/hope/lang/BenchmarkTest.java @@ -30,9 +30,9 @@ void testBenchmark() throws RunnerException { .warmupTime(TimeValue.seconds(5)) .warmupIterations(2) .measurementTime(TimeValue.seconds(10)) - .measurementIterations(2) + .measurementIterations(3) .threads(1) - .forks(3) + .forks(2) .shouldFailOnError(true) .shouldDoGC(true) .build(); From 944b29afd12e78e8638c76fb889eb057ab52b64e Mon Sep 17 00:00:00 2001 From: Rishabh Date: Mon, 6 Nov 2023 14:46:58 +0530 Subject: [PATCH 3/5] Creating baseline --- ...form.hope.lang.JsonPointerPerfTest.testPerfBulkEval.json | 6 +++--- ...rm.hope.lang.JsonPointerPerfTest.testPerfSingleEval.json | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hope-lang/perf/results/io.appform.hope.lang.JsonPointerPerfTest.testPerfBulkEval.json b/hope-lang/perf/results/io.appform.hope.lang.JsonPointerPerfTest.testPerfBulkEval.json index 02dd6ea..ca77847 100644 --- a/hope-lang/perf/results/io.appform.hope.lang.JsonPointerPerfTest.testPerfBulkEval.json +++ b/hope-lang/perf/results/io.appform.hope.lang.JsonPointerPerfTest.testPerfBulkEval.json @@ -1,8 +1,8 @@ { "name" : "io.appform.hope.lang.JsonPointerPerfTest.testPerfBulkEval", "mode" : "Throughput", - "iterations" : 2, + "iterations" : 3, "threads" : 1, - "forks" : 3, - "mean_ops" : 50739.771145738465 + "forks" : 2, + "mean_ops" : 116812.50719529158 } \ No newline at end of file diff --git a/hope-lang/perf/results/io.appform.hope.lang.JsonPointerPerfTest.testPerfSingleEval.json b/hope-lang/perf/results/io.appform.hope.lang.JsonPointerPerfTest.testPerfSingleEval.json index ec2824e..8631474 100644 --- a/hope-lang/perf/results/io.appform.hope.lang.JsonPointerPerfTest.testPerfSingleEval.json +++ b/hope-lang/perf/results/io.appform.hope.lang.JsonPointerPerfTest.testPerfSingleEval.json @@ -1,8 +1,8 @@ { "name" : "io.appform.hope.lang.JsonPointerPerfTest.testPerfSingleEval", "mode" : "Throughput", - "iterations" : 2, + "iterations" : 3, "threads" : 1, - "forks" : 3, - "mean_ops" : 14457.761592563897 + "forks" : 2, + "mean_ops" : 38475.51902529204 } \ No newline at end of file From 028f9a87028cd9de1464a7bd1a50587820cc3bd3 Mon Sep 17 00:00:00 2001 From: Rishabh Date: Mon, 6 Nov 2023 15:35:40 +0530 Subject: [PATCH 4/5] Using for loop instead of streams --- .../appform/hope/core/visitors/Evaluator.java | 50 +++++++++++++------ 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/hope-core/src/main/java/io/appform/hope/core/visitors/Evaluator.java b/hope-core/src/main/java/io/appform/hope/core/visitors/Evaluator.java index 70f5942..16067b7 100644 --- a/hope-core/src/main/java/io/appform/hope/core/visitors/Evaluator.java +++ b/hope-core/src/main/java/io/appform/hope/core/visitors/Evaluator.java @@ -17,7 +17,11 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import com.jayway.jsonpath.*; +import com.jayway.jsonpath.Configuration; +import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.JsonPath; +import com.jayway.jsonpath.Option; +import com.jayway.jsonpath.ParseContext; import com.jayway.jsonpath.spi.json.JacksonJsonNodeJsonProvider; import io.appform.hope.core.Evaluatable; import io.appform.hope.core.VisitorAdapter; @@ -25,16 +29,27 @@ import io.appform.hope.core.combiners.OrCombiner; import io.appform.hope.core.exceptions.errorstrategy.DefaultErrorHandlingStrategy; import io.appform.hope.core.exceptions.errorstrategy.ErrorHandlingStrategy; -import io.appform.hope.core.operators.*; +import io.appform.hope.core.operators.And; +import io.appform.hope.core.operators.Equals; +import io.appform.hope.core.operators.Greater; +import io.appform.hope.core.operators.GreaterEquals; +import io.appform.hope.core.operators.Lesser; +import io.appform.hope.core.operators.LesserEquals; +import io.appform.hope.core.operators.Not; +import io.appform.hope.core.operators.NotEquals; +import io.appform.hope.core.operators.Or; import io.appform.hope.core.utils.Converters; import lombok.Builder; import lombok.Data; import lombok.Getter; import lombok.val; -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.IntStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.OptionalInt; /** * Evaluates a hope expression @@ -58,9 +73,9 @@ public Evaluator() { public Evaluator(ErrorHandlingStrategy errorHandlingStrategy) { this.errorHandlingStrategy = errorHandlingStrategy; parseContext = JsonPath.using(Configuration.builder() - .jsonProvider(new JacksonJsonNodeJsonProvider()) - .options(Option.SUPPRESS_EXCEPTIONS) - .build()); + .jsonProvider(new JacksonJsonNodeJsonProvider()) + .options(Option.SUPPRESS_EXCEPTIONS) + .build()); } @@ -72,18 +87,25 @@ public List evaluate( final List evaluatables, final JsonNode node) { val logicEvaluator = new LogicEvaluator(new EvaluationContext(parseContext.parse(node), node, this)); - return evaluatables.stream() - .map(evaluatable -> evaluatable.accept(logicEvaluator)) - .collect(Collectors.toList()); + val list = new ArrayList(); + for (final Evaluatable evaluatable : evaluatables) { + Boolean accept = evaluatable.accept(logicEvaluator); + list.add(accept); + } + return list; } public OptionalInt evaluateFirst( final List rules, final JsonNode node) { val logicEvaluator = new LogicEvaluator(new EvaluationContext(parseContext.parse(node), node, this)); - return IntStream.range(0, rules.size()) - .filter(index -> rules.get(index).accept(logicEvaluator)) - .findFirst(); + val bound = rules.size(); + for (int index = 0; index < bound; index++) { + if (rules.get(index).accept(logicEvaluator)) { + return OptionalInt.of(index); + } + } + return OptionalInt.empty(); } @Data From c886a9e58be87b9a23cc42afb23924fa84866b91 Mon Sep 17 00:00:00 2001 From: Rishabh Date: Wed, 8 Nov 2023 14:42:21 +0530 Subject: [PATCH 5/5] Using forloop instead of streams --- .../appform/hope/core/utils/Converters.java | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/hope-core/src/main/java/io/appform/hope/core/utils/Converters.java b/hope-core/src/main/java/io/appform/hope/core/utils/Converters.java index 39263d5..3a4c906 100644 --- a/hope-core/src/main/java/io/appform/hope/core/utils/Converters.java +++ b/hope-core/src/main/java/io/appform/hope/core/utils/Converters.java @@ -25,12 +25,25 @@ import io.appform.hope.core.exceptions.errorstrategy.ErrorHandlingStrategy; import io.appform.hope.core.functions.FunctionRegistry; import io.appform.hope.core.functions.HopeFunction; -import io.appform.hope.core.values.*; +import io.appform.hope.core.values.ArrayValue; +import io.appform.hope.core.values.BooleanValue; +import io.appform.hope.core.values.FunctionValue; +import io.appform.hope.core.values.JsonPathValue; +import io.appform.hope.core.values.JsonPointerValue; +import io.appform.hope.core.values.NumericValue; +import io.appform.hope.core.values.ObjectValue; +import io.appform.hope.core.values.StringValue; import io.appform.hope.core.visitors.Evaluator; import lombok.extern.slf4j.Slf4j; +import lombok.val; import java.lang.reflect.Constructor; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Spliterator; +import java.util.Spliterators; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.StreamSupport; @@ -705,10 +718,12 @@ private static List arrayToObjectList( Evaluator.EvaluationContext evaluationContext, List values, Object defaultValue) { - return values - .stream() - .map(value -> objectValue(evaluationContext, value, defaultValue)) - .toList(); + val list = new ArrayList<>(); + for (final Value value : values) { + val o = objectValue(evaluationContext, value, defaultValue); + list.add(o); + } + return list; } }