Skip to content

Commit 0762a1a

Browse files
committed
Add microbenchmark for unified query APIs
Signed-off-by: Chen Dai <daichen@amazon.com>
1 parent 66529d9 commit 0762a1a

4 files changed

Lines changed: 121 additions & 1 deletion

File tree

api/src/test/java/org/opensearch/sql/api/UnifiedQueryTestBase.java renamed to api/src/testFixtures/java/org/opensearch/sql/api/UnifiedQueryTestBase.java

File renamed without changes.

benchmarks/README.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,18 @@ The microbenchmark suite is also handy for ad-hoc microbenchmarks but please rem
1010

1111
## Getting Started
1212

13-
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.
13+
Run all benchmarks from the project root directory:
14+
15+
```bash
16+
./gradlew :benchmarks:jmh
17+
```
18+
19+
Run specific benchmarks using the `-Pjmh.includes` parameter:
20+
21+
```bash
22+
./gradlew :benchmarks:jmh -Pjmh.includes='UnifiedQueryBenchmark'
23+
./gradlew :benchmarks:jmh -Pjmh.includes='UnifiedQueryBenchmark.plan.*'
24+
```
1425

1526
## Adding Microbenchmarks
1627

benchmarks/build.gradle

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ repositories {
1515
dependencies {
1616
implementation project(':core')
1717
implementation project(':opensearch')
18+
implementation project(':api')
19+
jmhImplementation testFixtures(project(':api'))
1820

1921
// Dependencies required by JMH micro benchmark
2022
api group: 'org.openjdk.jmh', name: 'jmh-core', version: '1.36'
@@ -30,4 +32,9 @@ spotless {
3032
}
3133
}
3234

35+
// JMH configuration passed via command line
36+
jmh {
37+
includes = project.hasProperty('jmh.includes') ? [project.property('jmh.includes')] : []
38+
}
39+
3340
compileJava.options.compilerArgs.addAll(["-processor", "org.openjdk.jmh.generators.BenchmarkProcessor"])
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package org.opensearch.sql.api;
7+
8+
import java.sql.PreparedStatement;
9+
import java.util.concurrent.TimeUnit;
10+
import org.apache.calcite.rel.RelNode;
11+
import org.apache.calcite.sql.dialect.SparkSqlDialect;
12+
import org.openjdk.jmh.annotations.Benchmark;
13+
import org.openjdk.jmh.annotations.BenchmarkMode;
14+
import org.openjdk.jmh.annotations.Fork;
15+
import org.openjdk.jmh.annotations.Level;
16+
import org.openjdk.jmh.annotations.Measurement;
17+
import org.openjdk.jmh.annotations.Mode;
18+
import org.openjdk.jmh.annotations.OutputTimeUnit;
19+
import org.openjdk.jmh.annotations.Param;
20+
import org.openjdk.jmh.annotations.Scope;
21+
import org.openjdk.jmh.annotations.Setup;
22+
import org.openjdk.jmh.annotations.State;
23+
import org.openjdk.jmh.annotations.TearDown;
24+
import org.openjdk.jmh.annotations.Warmup;
25+
import org.opensearch.sql.api.compiler.UnifiedQueryCompiler;
26+
import org.opensearch.sql.api.transpiler.UnifiedQueryTranspiler;
27+
28+
/**
29+
* JMH benchmark for measuring the overhead of unified query API components when processing PPL
30+
* queries. This provides baseline metrics for integration with the opensearch-spark repository.
31+
*
32+
* <p>Benchmarks cover:
33+
*
34+
* <ul>
35+
* <li>{@link UnifiedQueryPlanner}: PPL parsing and Calcite logical plan generation
36+
* <li>{@link UnifiedQueryTranspiler}: Logical plan to SQL string conversion
37+
* <li>{@link UnifiedQueryCompiler}: Logical plan to executable statement compilation
38+
* </ul>
39+
*
40+
* <p>Query patterns tested:
41+
*
42+
* <ul>
43+
* <li>Simple source scan
44+
* <li>Filter with WHERE clause
45+
* <li>Aggregation with GROUP BY
46+
* <li>Sort with ORDER BY
47+
* <li>Combined operations (filter + aggregation + sort)
48+
* </ul>
49+
*/
50+
@Warmup(iterations = 2, time = 1)
51+
@Measurement(iterations = 5, time = 1)
52+
@BenchmarkMode(Mode.AverageTime)
53+
@OutputTimeUnit(TimeUnit.MICROSECONDS)
54+
@State(Scope.Thread)
55+
@Fork(value = 1)
56+
public class UnifiedQueryBenchmark extends UnifiedQueryTestBase {
57+
58+
/** Common PPL query patterns for benchmarking. */
59+
@Param({
60+
"source = catalog.employees",
61+
"source = catalog.employees | where age > 30",
62+
"source = catalog.employees | stats count() by department",
63+
"source = catalog.employees | sort - age",
64+
"source = catalog.employees | where age > 25 | stats avg(age) by department | sort - department"
65+
})
66+
private String pplQuery;
67+
68+
private UnifiedQueryTranspiler transpiler;
69+
private UnifiedQueryCompiler compiler;
70+
71+
@Setup(Level.Trial)
72+
public void setUpBenchmark() {
73+
super.setUp();
74+
transpiler = UnifiedQueryTranspiler.builder().dialect(SparkSqlDialect.DEFAULT).build();
75+
compiler = new UnifiedQueryCompiler(context);
76+
}
77+
78+
@TearDown(Level.Trial)
79+
public void tearDownBenchmark() throws Exception {
80+
super.tearDown();
81+
}
82+
83+
/** Benchmarks PPL parsing and Calcite logical plan generation. */
84+
@Benchmark
85+
public RelNode planPplQuery() {
86+
return planner.plan(pplQuery);
87+
}
88+
89+
/** Benchmarks the full transpilation pipeline: PPL → logical plan → SQL string. */
90+
@Benchmark
91+
public String transpilePplToSparkSql() {
92+
RelNode plan = planner.plan(pplQuery);
93+
return transpiler.toSql(plan);
94+
}
95+
96+
/** Benchmarks the compilation pipeline: PPL → logical plan → executable statement. */
97+
@Benchmark
98+
public PreparedStatement compilePplQuery() {
99+
RelNode plan = planner.plan(pplQuery);
100+
return compiler.compile(plan);
101+
}
102+
}

0 commit comments

Comments
 (0)