Add micro benchmarks for unified query layer by dai-chen · Pull Request #5043 · opensearch-project/sql · GitHub
Skip to content

Add micro benchmarks for unified query layer#5043

Merged
dai-chen merged 5 commits into
opensearch-project:mainfrom
dai-chen:add-microbenchmark-for-unified-query-api
Jan 21, 2026
Merged

Add micro benchmarks for unified query layer#5043
dai-chen merged 5 commits into
opensearch-project:mainfrom
dai-chen:add-microbenchmark-for-unified-query-api

Conversation

@dai-chen

@dai-chen dai-chen commented Jan 13, 2026

Copy link
Copy Markdown
Collaborator

Description

Add JMH microbenchmarks for the unified query layer to establish baseline performance metrics for query planning, transpilation, compilation, and unified function evaluation.

Changes

  • UnifiedQueryBenchmark: benchmarks for query planning, SQL transpilation, and compilation pipelines across common PPL query patterns.
  • UnifiedFunctionBenchmark: benchmarks for function loading and evaluation covering representative functions from different categories (json, math, conditional, collection, string).

Sample Test Results

Benchmark                                                                                                                    (query)  Mode  Cnt  Score   Error  Units
UnifiedQueryBenchmark.compileQuery                                                                        source = catalog.employees  avgt    5  0.475 ± 0.309  ms/op
UnifiedQueryBenchmark.compileQuery                                                       source = catalog.employees | where age > 30  avgt    5  1.514 ± 1.226  ms/op
UnifiedQueryBenchmark.compileQuery                                          source = catalog.employees | stats count() by department  avgt    5  2.273 ± 4.164  ms/op
UnifiedQueryBenchmark.compileQuery                                                           source = catalog.employees | sort - age  avgt    5  0.636 ± 0.348  ms/op
UnifiedQueryBenchmark.compileQuery    source = catalog.employees | where age > 25 | stats avg(age) by department | sort - department  avgt    5  3.121 ± 3.492  ms/op
UnifiedQueryBenchmark.planQuery                                                                           source = catalog.employees  avgt    5  0.124 ± 0.006  ms/op
UnifiedQueryBenchmark.planQuery                                                          source = catalog.employees | where age > 30  avgt    5  0.140 ± 0.029  ms/op
UnifiedQueryBenchmark.planQuery                                             source = catalog.employees | stats count() by department  avgt    5  0.210 ± 0.028  ms/op
UnifiedQueryBenchmark.planQuery                                                              source = catalog.employees | sort - age  avgt    5  0.149 ± 0.016  ms/op
UnifiedQueryBenchmark.planQuery       source = catalog.employees | where age > 25 | stats avg(age) by department | sort - department  avgt    5  0.153 ± 0.020  ms/op
UnifiedQueryBenchmark.transpileToSql                                                                      source = catalog.employees  avgt    5  0.134 ± 0.021  ms/op
UnifiedQueryBenchmark.transpileToSql                                                     source = catalog.employees | where age > 30  avgt    5  0.143 ± 0.022  ms/op
UnifiedQueryBenchmark.transpileToSql                                        source = catalog.employees | stats count() by department  avgt    5  0.254 ± 0.051  ms/op
UnifiedQueryBenchmark.transpileToSql                                                         source = catalog.employees | sort - age  avgt    5  0.155 ± 0.020  ms/op
UnifiedQueryBenchmark.transpileToSql  source = catalog.employees | where age > 25 | stats avg(age) by department | sort - department  avgt    5  0.178 ± 0.047  ms/op
Benchmark                              (benchmarkSpec)  Mode  Cnt  Score   Error  Units
UnifiedFunctionBenchmark.evalFunction     JSON_EXTRACT  avgt    5  0.294 ± 0.040  ms/op
UnifiedFunctionBenchmark.evalFunction         COALESCE  avgt    5  0.367 ± 0.017  ms/op
UnifiedFunctionBenchmark.evalFunction           MVFIND  avgt    5  0.292 ± 0.115  ms/op
UnifiedFunctionBenchmark.evalFunction      REX_EXTRACT  avgt    5  0.341 ± 0.059  ms/op
UnifiedFunctionBenchmark.loadFunction     JSON_EXTRACT  avgt    5  0.293 ± 0.055  ms/op
UnifiedFunctionBenchmark.loadFunction         COALESCE  avgt    5  0.422 ± 0.105  ms/op
UnifiedFunctionBenchmark.loadFunction           MVFIND  avgt    5  0.277 ± 0.059  ms/op
UnifiedFunctionBenchmark.loadFunction      REX_EXTRACT  avgt    5  0.339 ± 0.052  ms/op

Related Issues

Resolves partially #4782

Check List

  • New functionality includes testing.
  • New functionality has been documented.
  • New functionality has javadoc added.
  • New functionality has a user manual doc added.
  • New PPL command checklist all confirmed.
  • API changes companion pull request created.
  • Commits are signed per the DCO using --signoff or -s.
  • Public documentation issue/PR created.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.

@dai-chen dai-chen self-assigned this Jan 13, 2026
@dai-chen dai-chen added the infrastructure Changes to infrastructure, testing, CI/CD, pipelines, etc. label Jan 13, 2026
@coderabbitai

coderabbitai Bot commented Jan 13, 2026

Copy link
Copy Markdown
Contributor

Signed-off-by: Chen Dai <daichen@amazon.com>
Signed-off-by: Chen Dai <daichen@amazon.com>
@dai-chen dai-chen force-pushed the add-microbenchmark-for-unified-query-api branch from 7988b7b to 8e50ba5 Compare January 14, 2026 22:17
Signed-off-by: Chen Dai <daichen@amazon.com>
@dai-chen dai-chen changed the title Add microbenchmark test for unified query APIs Add micro benchmarks for unified query layer Jan 15, 2026
Signed-off-by: Chen Dai <daichen@amazon.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@benchmarks/src/jmh/java/org/opensearch/sql/api/UnifiedQueryBenchmark.java`:
- Around line 81-86: The benchmark method compileQuery() returns a
PreparedStatement from compiler.compile(plan) but never closes it per iteration;
change the benchmark to close the PreparedStatement each iteration (either close
the returned PreparedStatement before returning or switch to void and close
within the method) so instances from compiler.compile(...) are released; update
the compileQuery() method to obtain RelNode plan = planner.plan(query), call
PreparedStatement stmt = compiler.compile(plan), ensure stmt.close() is invoked
in a finally block (or use try-with-resources) to guarantee per-iteration
cleanup.
🧹 Nitpick comments (1)
benchmarks/src/jmh/java/org/opensearch/sql/api/UnifiedFunctionBenchmark.java (1)

113-118: Consider adding a meaningful message to orElseThrow().

If the function is not found in the repository, the exception will have no context about which function failed to load.

Suggested improvement
     UnifiedFunction loadFunction(UnifiedFunctionRepository repository) {
       return repository
           .loadFunction(name())
           .map(desc -> desc.getBuilder().build(inputTypes))
-          .orElseThrow();
+          .orElseThrow(() -> new IllegalStateException("Function not found: " + name()));
     }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 66529d9 and 7938fbe.

📒 Files selected for processing (5)
  • api/src/testFixtures/java/org/opensearch/sql/api/UnifiedQueryTestBase.java
  • benchmarks/README.md
  • benchmarks/build.gradle
  • benchmarks/src/jmh/java/org/opensearch/sql/api/UnifiedFunctionBenchmark.java
  • benchmarks/src/jmh/java/org/opensearch/sql/api/UnifiedQueryBenchmark.java
🧰 Additional context used
📓 Path-based instructions (1)
**/*.java

📄 CodeRabbit inference engine (.rules/REVIEW_GUIDELINES.md)

**/*.java: Use PascalCase for class names (e.g., QueryExecutor)
Use camelCase for method and variable names (e.g., executeQuery)
Use UPPER_SNAKE_CASE for constants (e.g., MAX_RETRY_COUNT)
Keep methods under 20 lines with single responsibility
All public classes and methods must have proper JavaDoc
Use specific exception types with meaningful messages for error handling
Prefer Optional<T> for nullable returns in Java
Avoid unnecessary object creation in loops
Use StringBuilder for string concatenation in loops
Validate all user inputs, especially queries
Sanitize data before logging to prevent injection attacks
Use try-with-resources for proper resource cleanup in Java
Maintain Java 11 compatibility when possible for OpenSearch 2.x
Document Calcite-specific workarounds in code

Files:

  • benchmarks/src/jmh/java/org/opensearch/sql/api/UnifiedQueryBenchmark.java
  • benchmarks/src/jmh/java/org/opensearch/sql/api/UnifiedFunctionBenchmark.java

⚙️ CodeRabbit configuration file

**/*.java: - Flag methods >50 lines as potentially too complex - suggest refactoring

  • Flag classes >500 lines as needing organization review
  • Check for dead code, unused imports, and unused variables
  • Identify code reuse opportunities across similar implementations
  • Assess holistic maintainability - is code easy to understand and modify?
  • Flag code that appears AI-generated without sufficient human review
  • Verify Java naming conventions (PascalCase for classes, camelCase for methods/variables)
  • Check for proper JavaDoc on public classes and methods
  • Flag redundant comments that restate obvious code
  • Ensure proper error handling with specific exception types
  • Check for Optional usage instead of null returns
  • Validate proper use of try-with-resources for resource management

Files:

  • benchmarks/src/jmh/java/org/opensearch/sql/api/UnifiedQueryBenchmark.java
  • benchmarks/src/jmh/java/org/opensearch/sql/api/UnifiedFunctionBenchmark.java
🧠 Learnings (1)
📚 Learning: 2025-12-02T17:27:55.938Z
Learnt from: CR
Repo: opensearch-project/sql PR: 0
File: .rules/REVIEW_GUIDELINES.md:0-0
Timestamp: 2025-12-02T17:27:55.938Z
Learning: Test SQL generation and optimization paths for Calcite integration changes

Applied to files:

  • benchmarks/src/jmh/java/org/opensearch/sql/api/UnifiedQueryBenchmark.java
🧬 Code graph analysis (2)
benchmarks/src/jmh/java/org/opensearch/sql/api/UnifiedQueryBenchmark.java (1)
api/src/main/java/org/opensearch/sql/api/compiler/UnifiedQueryCompiler.java (1)
  • UnifiedQueryCompiler (24-71)
benchmarks/src/jmh/java/org/opensearch/sql/api/UnifiedFunctionBenchmark.java (1)
benchmarks/src/jmh/java/org/opensearch/sql/api/UnifiedQueryBenchmark.java (1)
  • Warmup (32-87)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (16)
  • GitHub Check: build-linux (25, integration)
  • GitHub Check: build-linux (21, unit)
  • GitHub Check: build-linux (21, integration)
  • GitHub Check: build-linux (25, unit)
  • GitHub Check: CodeQL-Scan (java)
  • GitHub Check: security-it-windows-macos (macos-14, 25)
  • GitHub Check: security-it-windows-macos (windows-latest, 21)
  • GitHub Check: build-windows-macos (macos-14, 21, doc)
  • GitHub Check: build-windows-macos (macos-14, 25, integration)
  • GitHub Check: build-windows-macos (macos-14, 21, unit)
  • GitHub Check: build-windows-macos (macos-14, 25, unit)
  • GitHub Check: build-windows-macos (macos-14, 21, integration)
  • GitHub Check: build-windows-macos (windows-latest, 25, -PbuildPlatform=windows, unit)
  • GitHub Check: build-windows-macos (windows-latest, 21, -PbuildPlatform=windows, integration)
  • GitHub Check: build-windows-macos (windows-latest, 21, -PbuildPlatform=windows, unit)
  • GitHub Check: build-windows-macos (windows-latest, 25, -PbuildPlatform=windows, integration)
🔇 Additional comments (9)
benchmarks/build.gradle (2)

36-39: JMH includes configuration looks good.

The configuration correctly reads from the project property and defaults to an empty list (run all benchmarks). This aligns with the README documentation.


19-20: Dependency additions are appropriate.

The api module dependency and testFixtures for jmhImplementation correctly expose the UnifiedQueryTestBase and other shared types needed by the new benchmarks.

benchmarks/README.md (1)

13-24: Clear and practical documentation.

The updated instructions are well-structured, showing both running all benchmarks and filtering by class/method patterns. The examples align with the jmh.includes configuration in build.gradle.

benchmarks/src/jmh/java/org/opensearch/sql/api/UnifiedFunctionBenchmark.java (3)

31-48: Well-structured benchmark class with proper JavaDoc.

The class is properly documented with JMH annotations matching UnifiedQueryBenchmark for consistency. The benchmark categories (json, math, conditional, collection, string) are clearly represented.


85-92: Correct use of @OperationsPerInvocation and Blackhole.

The evalFunction benchmark properly uses @OperationsPerInvocation(OPS) to report per-operation timings and Blackhole.consume() to prevent dead code elimination.


94-127: Clean enum design for benchmark specifications.

The BenchmarkSpec enum effectively encapsulates function test cases with their input types and sample values. The helper methods inputTypes() and sampleInputs() improve readability.

benchmarks/src/jmh/java/org/opensearch/sql/api/UnifiedQueryBenchmark.java (3)

28-38: Well-structured benchmark class with consistent JMH configuration.

The class properly documents its purpose and uses consistent JMH annotations matching UnifiedFunctionBenchmark. The benchmark methods are focused and return results to prevent dead code elimination.


40-48: Good coverage of representative PPL query patterns.

The query parameters cover essential operations: simple source, filtering (where), aggregation (stats), sorting, and combined pipelines. This provides meaningful baseline metrics.


68-79: Benchmark methods correctly return values.

Both planQuery() and transpileToSql() return their results, preventing JIT dead code elimination without needing Blackhole. This is the recommended JMH pattern when the result is a reference type.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment thread benchmarks/src/jmh/java/org/opensearch/sql/api/UnifiedQueryBenchmark.java Outdated
Signed-off-by: Chen Dai <daichen@amazon.com>
@dai-chen dai-chen merged commit cee7f6b into opensearch-project:main Jan 21, 2026
40 checks passed
@opensearch-trigger-bot

Copy link
Copy Markdown
Contributor

dai-chen added a commit to dai-chen/sql-1 that referenced this pull request Jan 21, 2026
* Add microbenchmark for unified query APIs

Signed-off-by: Chen Dai <daichen@amazon.com>

* Add benchmark for unified function

Signed-off-by: Chen Dai <daichen@amazon.com>

* Refactor javadoc and helper method

Signed-off-by: Chen Dai <daichen@amazon.com>

* Fix spotless check failure

Signed-off-by: Chen Dai <daichen@amazon.com>

* Address CodeRabit comment

Signed-off-by: Chen Dai <daichen@amazon.com>

---------

Signed-off-by: Chen Dai <daichen@amazon.com>
(cherry picked from commit cee7f6b)
@LantaoJin LantaoJin added the backport-manually Filed a PR to backport manually. label Jan 22, 2026
qianheng-aws pushed a commit that referenced this pull request Jan 22, 2026
* Add microbenchmark for unified query APIs



* Add benchmark for unified function



* Refactor javadoc and helper method



* Fix spotless check failure



* Address CodeRabit comment



---------


(cherry picked from commit cee7f6b)

Signed-off-by: Chen Dai <daichen@amazon.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport 2.19-dev backport-failed backport-manually Filed a PR to backport manually. infrastructure Changes to infrastructure, testing, CI/CD, pipelines, etc.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants