Skip to content

JAVA-6303: OpenTelemetry overhead benchmark suite [DO-NOT-MERGE] - #2080

Draft
nhachicha wants to merge 3 commits into
mongodb:mainfrom
nhachicha:nh/otel-benchmark-drivers3620
Draft

nhachicha wants to merge 3 commits into
mongodb:mainfrom
nhachicha:nh/otel-benchmark-drivers3620

Conversation

@nhachicha

@nhachicha nhachicha commented Oct 15, 2026 •

Copy link
Copy Markdown
Collaborator

JAVA-6303

Benchmark harness for the OpenTelemetry spec's "Performance Implications" section (mongodb/specifications#1986, DRIVERS-3620). Draft: for discussion of method and the Java configuration mapping before this is wired into Evergreen.

What it adds

  • OtelBenchmarkSuite (driver-benchmarks/.../otel/): runs DriverBench "Small doc insertOne" and "Find one by ID", sync and Reactive Streams, under one tracing configuration per JVM, selected by -Dorg.mongodb.benchmarks.otel.config:
    • off: no ObservabilitySettings (baseline)
    • api-only: ObservationRegistry.create() with no handlers; Micrometer short-circuits to a no-op observation, so the driver runs its instrumentation code but nothing records
    • sdk-ratio: OTel SdkTracerProvider with traceIdRatioBased(0.01), bridged via DefaultTracingObservationHandler, no exporter or processor
    • sdk-always: same with alwaysOn()
  • InstrumentedBenchmarkRunner: wall time, process CPU time and GC time per iteration; reports MB/s, wall/op, CPU/op, CPU-excluding-GC/op.
  • -Dorg.mongodb.benchmarks.otel.verify=true installs a counting span processor and reports spans per op (2.00 under sdk-always, 0.02 under sdk-ratio), for wiring checks only.
  • otel-bench.py: one JVM per configuration, configurations interleaved and order rotated per repetition, writes REPORT.md/summary.json; accepts a pre-OTel worktree for the spec's one-time comparison.
  • otel-compare-langs.py, otel-compare-runs.py: cross-language and before/after tables.

New benchmark-only deps in the catalog: opentelemetry-bom 1.53.0, opentelemetry-sdk-trace, micrometer-tracing-bridge-otel. Used only by driver-benchmarks; the driver itself is unchanged.

Results (Apple M4 Max, mongod 8.2.6, Temurin 17, 5 interleaved reps, medians)

Loss vs off / added CPU µs per op (excl. GC):

API Task api-only sdk-ratio 1% sdk-always off vs pre-OTel commit
sync Small doc insertOne +4.2% / +1.6 +9.6% / +4.5 +10.8% / +5.3 +0.8%
sync Find one by ID +5.4% / +2.2 +12.2% / +5.6 +13.3% / +6.7 −1.1%
async Small doc insertOne +3.1% / +1.7 +5.5% / +4.3 +6.3% / +5.5 −0.4%
async Find one by ID +2.6% / +0.7 +6.3% / +4.5 +7.5% / +5.5 +0.6%

Pre-OTel commit is e1bf5f57b1 (parent of #1695). A follow-up draft gates attribute building on the sampling decision and roughly halves the added CPU per op.

Usage

./gradlew :driver-benchmarks:runOtel \
  -Dorg.mongodb.benchmarks.data=<driver-performance-test-data>/ \
  -Dorg.mongodb.benchmarks.output=/tmp/out.json \
  -Dorg.mongodb.benchmarks.otel.config=sdk-ratio

python3 -I driver-benchmarks/otel-bench.py --data <data> --out <dir> --reps 5 [--pre-otel-worktree <path>]

Open points

  • Should run as an Evergreen perf variant; these numbers are from a laptop.
  • Async tasks block per operation (per-op overhead, not pipelined throughput).
  • api-only mapping for a Micrometer driver is a judgement call; raised on the spec PR.

Implements the benchmarking requirements of the OpenTelemetry spec's
"Performance Implications" section (mongodb/specifications#1986):

- OtelBenchmarkSuite runs the DriverBench "Small doc insertOne" and
  "Find one by ID" tasks, sync and Reactive Streams, under one tracing
  configuration per JVM: off, api-only (ObservationRegistry with no
  handlers), sdk-ratio (OTel SDK, 1% TraceIdRatioBased sampler) and
  sdk-always (alwaysOn). The harness installs the SDK; no exporter or
  span processor is installed. A verify mode counts spans per operation.
- InstrumentedBenchmarkRunner records wall time, process CPU time and
  GC time per iteration, reporting MB/s and CPU-per-op excluding GC.
- otel-bench.py runs the configurations interleaved with rotated order
  across repetitions and writes a report; a pre-OTel baseline worktree
  can be included for the spec's one-time comparison.
- otel-compare-langs.py and otel-compare-runs.py produce cross-language
  and before/after tables.

New benchmark-only dependencies (micrometer-tracing-bridge-otel,
opentelemetry-sdk-trace via opentelemetry-bom) are declared in the
version catalog and used only by driver-benchmarks.

Run: ./gradlew :driver-benchmarks:runOtel -Dorg.mongodb.benchmarks.data=...
       -Dorg.mongodb.benchmarks.output=... -Dorg.mongodb.benchmarks.otel.config=sdk-ratio
@nhachicha nhachicha self-assigned this Oct 15, 2026
@nhachicha nhachicha changed the title DRIVERS-3620: OpenTelemetry overhead benchmark suite DRIVERS-3620: OpenTelemetry overhead benchmark suite [DO-NOT-MERGE] Oct 15, 2026
…rgreen

Runs the DRIVERS-3620 benchmark on the existing perf variant alongside
perf-task and perf-netty-task: a standalone v8.0-perf server, the four
tracing configurations interleaved with rotated order (3 repetitions by
default via OTEL_BENCH_REPS), and upload through send-dashboard-data.

otel-bench.py gains --dashboard, which writes results.json in the
dashboard shape: one series per configuration/API/task with MB/s and
CPU per op, plus throughput loss and added CPU relative to `off` as
metrics of their own, as the spec asks drivers to record.
@nhachicha nhachicha changed the title DRIVERS-3620: OpenTelemetry overhead benchmark suite [DO-NOT-MERGE] JAVA-6303: OpenTelemetry overhead benchmark suite [DO-NOT-MERGE] Oct 15, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant