From 411bf9ddc36fa992530f00e940aa0f54211fe869 Mon Sep 17 00:00:00 2001
From: Jack Berg <34418638+jack-berg@users.noreply.github.com>
Date: Fri, 11 Sep 2026 13:36:12 -0500
Subject: [PATCH 1/2] Update otel benchmark dependencies, add otel bound
instrument scenarios
---
benchmarks/pom.xml | 23 ++++
.../metrics/benchmarks/CounterBenchmark.java | 64 +++++++++++
.../benchmarks/HistogramBenchmark.java | 108 ++++++++++++++++++
3 files changed, 195 insertions(+)
diff --git a/benchmarks/pom.xml b/benchmarks/pom.xml
index 6d8c9c5c45..32170a40cb 100644
--- a/benchmarks/pom.xml
+++ b/benchmarks/pom.xml
@@ -19,12 +19,31 @@
1.37
0.16.0
3.0.2
+
+ 1.66.0
true
true
+
+
+ io.opentelemetry
+ opentelemetry-bom
+ ${benchmark.otel.version}
+ pom
+ import
+
+
+ io.opentelemetry
+ opentelemetry-bom-alpha
+ ${benchmark.otel.version}-alpha
+ pom
+ import
+
io.opentelemetry.instrumentation
opentelemetry-instrumentation-bom-alpha
@@ -73,6 +92,10 @@
io.opentelemetry
opentelemetry-sdk-testing
+
+ io.opentelemetry
+ opentelemetry-api-incubator
+
${project.artifactId}
diff --git a/benchmarks/src/main/java/io/prometheus/metrics/benchmarks/CounterBenchmark.java b/benchmarks/src/main/java/io/prometheus/metrics/benchmarks/CounterBenchmark.java
index d8b75e437c..2b612a7f24 100644
--- a/benchmarks/src/main/java/io/prometheus/metrics/benchmarks/CounterBenchmark.java
+++ b/benchmarks/src/main/java/io/prometheus/metrics/benchmarks/CounterBenchmark.java
@@ -3,10 +3,15 @@
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.incubator.metrics.BoundDoubleCounter;
+import io.opentelemetry.api.incubator.metrics.BoundLongCounter;
+import io.opentelemetry.api.incubator.metrics.ExtendedDoubleCounter;
+import io.opentelemetry.api.incubator.metrics.ExtendedLongCounter;
import io.opentelemetry.api.metrics.DoubleCounter;
import io.opentelemetry.api.metrics.LongCounter;
import io.opentelemetry.api.metrics.Meter;
import io.opentelemetry.sdk.OpenTelemetrySdk;
+import io.opentelemetry.sdk.metrics.ExemplarFilter;
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.testing.exporter.InMemoryMetricReader;
@@ -94,6 +99,7 @@ public OpenTelemetryCounter() {
SdkMeterProvider.builder()
.registerMetricReader(InMemoryMetricReader.create())
.setResource(Resource.getDefault())
+ .setExemplarFilter(ExemplarFilter.alwaysOff())
.build();
OpenTelemetry openTelemetry =
OpenTelemetrySdk.builder().setMeterProvider(sdkMeterProvider).build();
@@ -111,6 +117,45 @@ public OpenTelemetryCounter() {
}
}
+ /**
+ * OpenTelemetry counter using the incubator "bound instrument" API, which pre-binds a set of
+ * attributes at initialization time to avoid a per-record attribute map lookup.
+ */
+ @State(Scope.Benchmark)
+ public static class OpenTelemetryBoundCounter {
+
+ final BoundLongCounter longCounter;
+ final BoundDoubleCounter doubleCounter;
+
+ public OpenTelemetryBoundCounter() {
+
+ SdkMeterProvider sdkMeterProvider =
+ SdkMeterProvider.builder()
+ .registerMetricReader(InMemoryMetricReader.create())
+ .setResource(Resource.getDefault())
+ .setExemplarFilter(ExemplarFilter.alwaysOff())
+ .build();
+ OpenTelemetry openTelemetry =
+ OpenTelemetrySdk.builder().setMeterProvider(sdkMeterProvider).build();
+ Meter meter =
+ openTelemetry
+ .meterBuilder("instrumentation-library-name")
+ .setInstrumentationVersion("1.0.0")
+ .build();
+ Attributes attributes =
+ Attributes.of(
+ AttributeKey.stringKey("path"), "/",
+ AttributeKey.stringKey("status"), "200");
+ this.longCounter =
+ ((ExtendedLongCounter) meter.counterBuilder("test1").setDescription("test").build())
+ .bind(attributes);
+ this.doubleCounter =
+ ((ExtendedDoubleCounter)
+ meter.counterBuilder("test2").ofDoubles().setDescription("test").build())
+ .bind(attributes);
+ }
+ }
+
@Benchmark
@Threads(4)
public CounterDataPoint prometheusAdd(RandomNumbers randomNumbers, PrometheusCounter counter) {
@@ -156,6 +201,25 @@ public LongCounter openTelemetryIncNoLabels(OpenTelemetryCounter counter) {
return counter.longCounter;
}
+ @Benchmark
+ @Threads(4)
+ public BoundDoubleCounter openTelemetryBoundAdd(
+ RandomNumbers randomNumbers, OpenTelemetryBoundCounter counter) {
+ for (int i = 0; i < randomNumbers.randomNumbers.length; i++) {
+ counter.doubleCounter.add(randomNumbers.randomNumbers[i]);
+ }
+ return counter.doubleCounter;
+ }
+
+ @Benchmark
+ @Threads(4)
+ public BoundLongCounter openTelemetryBoundInc(OpenTelemetryBoundCounter counter) {
+ for (int i = 0; i < 10 * 1024; i++) {
+ counter.longCounter.add(1);
+ }
+ return counter.longCounter;
+ }
+
@Benchmark
@Threads(4)
public io.prometheus.client.Counter.Child simpleclientAdd(
diff --git a/benchmarks/src/main/java/io/prometheus/metrics/benchmarks/HistogramBenchmark.java b/benchmarks/src/main/java/io/prometheus/metrics/benchmarks/HistogramBenchmark.java
index 41b7097dbc..eefb963592 100644
--- a/benchmarks/src/main/java/io/prometheus/metrics/benchmarks/HistogramBenchmark.java
+++ b/benchmarks/src/main/java/io/prometheus/metrics/benchmarks/HistogramBenchmark.java
@@ -1,9 +1,14 @@
package io.prometheus.metrics.benchmarks;
import io.opentelemetry.api.OpenTelemetry;
+import io.opentelemetry.api.common.AttributeKey;
+import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.incubator.metrics.BoundDoubleHistogram;
+import io.opentelemetry.api.incubator.metrics.ExtendedDoubleHistogram;
import io.opentelemetry.api.metrics.Meter;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.metrics.Aggregation;
+import io.opentelemetry.sdk.metrics.ExemplarFilter;
import io.opentelemetry.sdk.metrics.InstrumentSelector;
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
import io.opentelemetry.sdk.metrics.View;
@@ -95,6 +100,7 @@ public OpenTelemetryClassicHistogram() {
SdkMeterProvider.builder()
.registerMetricReader(InMemoryMetricReader.create())
.setResource(Resource.getDefault())
+ .setExemplarFilter(ExemplarFilter.alwaysOff())
.registerView(
InstrumentSelector.builder().setName("test").build(),
View.builder()
@@ -126,6 +132,7 @@ public OpenTelemetryExponentialHistogram() {
SdkMeterProvider.builder()
.registerMetricReader(InMemoryMetricReader.create())
.setResource(Resource.getDefault())
+ .setExemplarFilter(ExemplarFilter.alwaysOff())
.registerView(
InstrumentSelector.builder().setName("test").build(),
View.builder()
@@ -143,6 +150,87 @@ public OpenTelemetryExponentialHistogram() {
}
}
+ /**
+ * OpenTelemetry classic histogram using the incubator "bound instrument" API to pre-bind
+ * attributes at initialization time.
+ */
+ @State(Scope.Benchmark)
+ public static class OpenTelemetryBoundClassicHistogram {
+
+ final BoundDoubleHistogram histogram;
+
+ public OpenTelemetryBoundClassicHistogram() {
+ SdkMeterProvider sdkMeterProvider =
+ SdkMeterProvider.builder()
+ .registerMetricReader(InMemoryMetricReader.create())
+ .setResource(Resource.getDefault())
+ .setExemplarFilter(ExemplarFilter.alwaysOff())
+ .registerView(
+ InstrumentSelector.builder().setName("test").build(),
+ View.builder()
+ .setAggregation(
+ Aggregation.explicitBucketHistogram(
+ Arrays.asList(
+ .005, .01, .025, .05, .1, .25, .5, 1.0, 2.5, 5.0, 10.0)))
+ .build())
+ .build();
+ OpenTelemetry openTelemetry =
+ OpenTelemetrySdk.builder().setMeterProvider(sdkMeterProvider).build();
+ Meter meter =
+ openTelemetry
+ .meterBuilder("instrumentation-library-name")
+ .setInstrumentationVersion("1.0.0")
+ .build();
+ Attributes attributes =
+ Attributes.of(
+ AttributeKey.stringKey("path"), "/",
+ AttributeKey.stringKey("status"), "200");
+ this.histogram =
+ ((ExtendedDoubleHistogram)
+ meter.histogramBuilder("test").setDescription("test").build())
+ .bind(attributes);
+ }
+ }
+
+ /**
+ * OpenTelemetry exponential histogram using the incubator "bound instrument" API to pre-bind
+ * attributes at initialization time.
+ */
+ @State(Scope.Benchmark)
+ public static class OpenTelemetryBoundExponentialHistogram {
+
+ final BoundDoubleHistogram histogram;
+
+ public OpenTelemetryBoundExponentialHistogram() {
+ SdkMeterProvider sdkMeterProvider =
+ SdkMeterProvider.builder()
+ .registerMetricReader(InMemoryMetricReader.create())
+ .setResource(Resource.getDefault())
+ .setExemplarFilter(ExemplarFilter.alwaysOff())
+ .registerView(
+ InstrumentSelector.builder().setName("test").build(),
+ View.builder()
+ .setAggregation(Aggregation.base2ExponentialBucketHistogram(10_000, 5))
+ .build())
+ .build();
+ OpenTelemetry openTelemetry =
+ OpenTelemetrySdk.builder().setMeterProvider(sdkMeterProvider).build();
+ Meter meter =
+ openTelemetry
+ .meterBuilder("instrumentation-library-name")
+ .setInstrumentationVersion("1.0.0")
+ .build();
+ Attributes attributes =
+ Attributes.of(
+ AttributeKey.stringKey("path"), "/",
+ AttributeKey.stringKey("status"), "200");
+ this.histogram =
+ ((ExtendedDoubleHistogram)
+ meter.histogramBuilder("test").setDescription("test").build())
+ .bind(attributes);
+ }
+ }
+
@Benchmark
@Threads(4)
public Histogram prometheusClassic(
@@ -212,4 +300,24 @@ public io.opentelemetry.api.metrics.DoubleHistogram openTelemetryExponential(
}
return histogram.histogram;
}
+
+ @Benchmark
+ @Threads(4)
+ public BoundDoubleHistogram openTelemetryBoundClassic(
+ RandomNumbers randomNumbers, OpenTelemetryBoundClassicHistogram histogram) {
+ for (int i = 0; i < randomNumbers.randomNumbers.length; i++) {
+ histogram.histogram.record(randomNumbers.randomNumbers[i]);
+ }
+ return histogram.histogram;
+ }
+
+ @Benchmark
+ @Threads(4)
+ public BoundDoubleHistogram openTelemetryBoundExponential(
+ RandomNumbers randomNumbers, OpenTelemetryBoundExponentialHistogram histogram) {
+ for (int i = 0; i < randomNumbers.randomNumbers.length; i++) {
+ histogram.histogram.record(randomNumbers.randomNumbers[i]);
+ }
+ return histogram.histogram;
+ }
}
From 75152aa211a012b4f36aee62835a8b621a223bd2 Mon Sep 17 00:00:00 2001
From: Jack Berg <34418638+jack-berg@users.noreply.github.com>
Date: Fri, 11 Sep 2026 18:33:34 -0500
Subject: [PATCH 2/2] lint
---
.../prometheus/metrics/benchmarks/HistogramBenchmark.java | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/benchmarks/src/main/java/io/prometheus/metrics/benchmarks/HistogramBenchmark.java b/benchmarks/src/main/java/io/prometheus/metrics/benchmarks/HistogramBenchmark.java
index eefb963592..3878568925 100644
--- a/benchmarks/src/main/java/io/prometheus/metrics/benchmarks/HistogramBenchmark.java
+++ b/benchmarks/src/main/java/io/prometheus/metrics/benchmarks/HistogramBenchmark.java
@@ -186,8 +186,7 @@ public OpenTelemetryBoundClassicHistogram() {
AttributeKey.stringKey("path"), "/",
AttributeKey.stringKey("status"), "200");
this.histogram =
- ((ExtendedDoubleHistogram)
- meter.histogramBuilder("test").setDescription("test").build())
+ ((ExtendedDoubleHistogram) meter.histogramBuilder("test").setDescription("test").build())
.bind(attributes);
}
}
@@ -225,8 +224,7 @@ public OpenTelemetryBoundExponentialHistogram() {
AttributeKey.stringKey("path"), "/",
AttributeKey.stringKey("status"), "200");
this.histogram =
- ((ExtendedDoubleHistogram)
- meter.histogramBuilder("test").setDescription("test").build())
+ ((ExtendedDoubleHistogram) meter.histogramBuilder("test").setDescription("test").build())
.bind(attributes);
}
}