opensearch-project / opensearch-project/opensearch-java
[FEATURE] Add JMH Benchmark Module
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 165
- Forks
- 250
- Avg merge
- 1d 18h
- Merged PRs (30d)
- 26
Description
Is your feature request related to a problem?
The opensearch-java client has no performance benchmarking infrastructure. There is currently no way to:
- Measure the throughput or latency of BulkIngester under different configurations
- Detect performance regressions introduced by code changes
- Compare the cost of different serialization strategies (e.g. raw POJO vs BinaryData)
- Validate that optimizations like increased maxConcurrentRequests or batch sizing actually improve end-to-end throughput
Without a benchmark module, performance work relies entirely on ad-hoc scripts written outside the repository, making results hard to reproduce and compare across contributors.
What solution would you like?
A benchmarks/ submodule using JMH (Java Microbenchmark Harness) (https://github.com/openjdk/jmh) via the me.champeau.jmh(https://github.com/melix/jmh-gradle-plugin) Gradle plugin.
Proposed module structure
benchmarks/
├── build.gradle.kts # JMH plugin + dependencies
└── src/jmh/java/org/opensearch/client/benchmarks/
└── BulkIngesterBenchmark.java # end-to-end throughput benchmark
BulkIngesterBenchmark — initial benchmark
Measures end-to-end BulkIngester throughput (ops/s) against a live OpenSearch cluster, parameterized on:
- maxOperations — operations per bulk flush (e.g. 1000, 5000, 10000)
- maxSize — max bytes size per bulk flush (e.g. 5MB, 10MB)
- maxConcurrentRequests — in-flight bulk request limit (e.g. 1, 2, 4, 8)
Key design decisions:
- Uses @Threads(Threads.MAX) to simulate concurrent producers and reach steady-state throughput
- Pre-serializes documents to BinaryData once at @Setup to isolate transport cost from serialization cost
- Creates a fresh timestamped index per trial and deletes it in @TearDown
- Supports HTTPS + basic auth via system properties for testing against remote clusters
Run against a local cluster
./gradlew :benchmarks:jmh -Pbenchmark=BulkIngesterBenchmark
Run against a remote cluster with HTTPS + basic auth
./gradlew :benchmarks:jmh -Pbenchmark=BulkIngesterBenchmark
-Dbenchmark.scheme=https
-Dbenchmark.host=my-cluster.example.com
-Dbenchmark.port=443
-Dbenchmark.user=admin
-Dbenchmark.password=secret
Sample output:
Benchmark (batchSize) (maxConcurrentRequests) Mode Cnt Score Error Units
BulkIngesterBenchmark.bulkIndexThroughput 1000 1 thrpt 10 28,776 ± 1,839 ops/s
BulkIngesterBenchmark.bulkIndexThroughput 5000 1 thrpt 10 35,395 ± 1,423 ops/s
BulkIngesterBenchmark.bulkIndexThroughput 10000 1 thrpt 10 35,507 ± 2,873 ops/s
BulkIngesterBenchmark.bulkIndexThroughput N/A 1 thrpt 10 35,241 ± 1,102 ops/s
What alternatives have you considered?
OpenSearch Benchmark (OSB) maybe an option, but OSB drives OpenSearch directly using its own internal HTTP client. It measures what the cluster can handle — indexing throughput, query latency, segment merge cost. It has no knowledge of the Java client's internal architecture: BulkIngester's buffer management, the maxConcurrentRequests semaphore, the ReentrantLock contention, serialization cost, or connection pool behavior.
If a code change in BulkIngester introduces a lock contention bug that halves throughput, OSB would never detect it — because OSB never calls BulkIngester.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the proposed benchmarks/build.gradle.kts module and src/jmh/java/org/opensearch/client/benchmarks/BulkIngesterBenchmark.java, then review the existing Gradle project structure and BulkIngester API. Run ./gradlew :benchmarks:jmh -Pbenchmark=BulkIngesterBenchmark against a local cluster. Done means the JMH benchmark supports the requested parameters, measures throughput, and cleans up its timestamped index.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- performance
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100