From db9be18c0bf354cfc9663b6bbe3de7578e4a401d Mon Sep 17 00:00:00 2001 From: "opensearch-trigger-bot[bot]" <98922864+opensearch-trigger-bot[bot]@users.noreply.github.com> Date: Mon, 23 Jan 2023 13:27:21 -0800 Subject: [PATCH] Add micro benchmark by JMH (#1278) (#1291) * Add benchmark module and test implicit cast Signed-off-by: Chen Dai * Benchmark the second approach from Yury Signed-off-by: Chen Dai * Refactor code to make benchmark module for future use Signed-off-by: Chen Dai * Add readme Signed-off-by: Chen Dai * Move benchmark class to right source location Signed-off-by: Chen Dai * Change depedency accessiblity from api to impl Signed-off-by: Chen Dai Signed-off-by: Chen Dai (cherry picked from commit ff9ac16527b8dff216bfa64a5572fbb46d1b11e0) Co-authored-by: Chen Dai --- benchmarks/README.md | 19 +++++ benchmarks/build.gradle | 23 ++++++ .../ComparisonOperatorBenchmark.java | 73 +++++++++++++++++++ settings.gradle | 1 + 4 files changed, 116 insertions(+) create mode 100644 benchmarks/README.md create mode 100644 benchmarks/build.gradle create mode 100644 benchmarks/src/jmh/java/org/opensearch/sql/expression/operator/predicate/ComparisonOperatorBenchmark.java diff --git a/benchmarks/README.md b/benchmarks/README.md new file mode 100644 index 0000000000..d90eb850db --- /dev/null +++ b/benchmarks/README.md @@ -0,0 +1,19 @@ +# OpenSearch SQL/PPL Microbenchmark Suite + +This directory contains the microbenchmark suite of OpenSearch SQL/PPL. It relies on [JMH](http://openjdk.java.net/projects/code-tools/jmh/). + +## Purpose + +Microbenchmarks are intended to spot performance regressions in performance-critical components. + +The microbenchmark suite is also handy for ad-hoc microbenchmarks but please remove them again before merging your PR. + +## Getting Started + +Just run `./gradlew :benchmarks:jmh` from the project root directory or run specific benchmark via your IDE. It will build all microbenchmarks, execute them and print the result. + +## Adding Microbenchmarks + +Before adding a new microbenchmark, make yourself familiar with the JMH API. You can check our existing microbenchmarks and also the [JMH samples](http://hg.openjdk.java.net/code-tools/jmh/file/tip/jmh-samples/src/main/java/org/openjdk/jmh/samples/). + +In contrast to tests, the actual name of the benchmark class is not relevant to JMH. However, stick to the naming convention and end the class name of a benchmark with `Benchmark`. To have JMH execute a benchmark, annotate the respective methods with `@Benchmark`. \ No newline at end of file diff --git a/benchmarks/build.gradle b/benchmarks/build.gradle new file mode 100644 index 0000000000..f01819be14 --- /dev/null +++ b/benchmarks/build.gradle @@ -0,0 +1,23 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +plugins { + id 'java-library' + id "me.champeau.jmh" version "0.6.8" +} + +repositories { + mavenCentral() +} + +dependencies { + implementation project(':core') + + // Dependencies required by JMH micro benchmark + api group: 'org.openjdk.jmh', name: 'jmh-core', version: '1.36' + annotationProcessor group: 'org.openjdk.jmh', name: 'jmh-generator-annprocess', version: '1.36' +} + +compileJava.options.compilerArgs.addAll(["-processor", "org.openjdk.jmh.generators.BenchmarkProcessor"]) \ No newline at end of file diff --git a/benchmarks/src/jmh/java/org/opensearch/sql/expression/operator/predicate/ComparisonOperatorBenchmark.java b/benchmarks/src/jmh/java/org/opensearch/sql/expression/operator/predicate/ComparisonOperatorBenchmark.java new file mode 100644 index 0000000000..d2642dd645 --- /dev/null +++ b/benchmarks/src/jmh/java/org/opensearch/sql/expression/operator/predicate/ComparisonOperatorBenchmark.java @@ -0,0 +1,73 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.sql.expression.operator.predicate; + +import static org.opensearch.sql.data.model.ExprValueUtils.fromObjectValue; +import static org.opensearch.sql.data.model.ExprValueUtils.integerValue; +import static org.opensearch.sql.data.model.ExprValueUtils.stringValue; +import static org.opensearch.sql.data.type.ExprCoreType.DATE; +import static org.opensearch.sql.expression.DSL.literal; + +import com.google.common.collect.ImmutableMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.opensearch.sql.data.model.ExprValue; +import org.opensearch.sql.expression.DSL; +import org.opensearch.sql.expression.Expression; +import org.opensearch.sql.expression.FunctionExpression; + +@Warmup(iterations = 1) +@Measurement(iterations = 3) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Thread) +@Fork(value = 1) +public class ComparisonOperatorBenchmark { + + @Param(value = { "int", "string", "date" }) + private String testDataType; + + private final Map params = + ImmutableMap.builder() + .put("int", integerValue(1)) + .put("string", stringValue("hello")) + .put("date", fromObjectValue("2022-01-12", DATE)) + .build(); + + @Benchmark + public void testEqualOperator() { + run(DSL::equal); + } + + @Benchmark + public void testLessOperator() { + run(DSL::less); + } + + @Benchmark + public void testGreaterOperator() { + run(DSL::greater); + } + + private void run(Function dsl) { + ExprValue param = params.get(testDataType); + FunctionExpression func = dsl.apply(new Expression[] { + literal(param), literal(param) + }); + func.valueOf(); + } +} diff --git a/settings.gradle b/settings.gradle index 89d7380801..7def8a746c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -18,3 +18,4 @@ include 'doctest' include 'legacy' include 'sql' include 'prometheus' +include 'benchmarks'