diff --git a/benchmarks/pom.xml b/benchmarks/pom.xml index 5f1a1a898..b80df7a25 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 06d2648f9..c0cb16b1d 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; @@ -136,6 +141,7 @@ public OpenTelemetryCounter() { SdkMeterProvider.builder() .registerMetricReader(InMemoryMetricReader.create()) .setResource(Resource.getDefault()) + .setExemplarFilter(ExemplarFilter.alwaysOff()) .build(); OpenTelemetry openTelemetry = OpenTelemetrySdk.builder().setMeterProvider(sdkMeterProvider).build(); @@ -153,6 +159,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) { @@ -198,6 +243,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 41b7097db..29f730e6f 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; @@ -88,6 +93,7 @@ public SimpleclientHistogram() { public static class OpenTelemetryClassicHistogram { final io.opentelemetry.api.metrics.DoubleHistogram histogram; + final Attributes attributes; public OpenTelemetryClassicHistogram() { @@ -95,6 +101,7 @@ public OpenTelemetryClassicHistogram() { SdkMeterProvider.builder() .registerMetricReader(InMemoryMetricReader.create()) .setResource(Resource.getDefault()) + .setExemplarFilter(ExemplarFilter.alwaysOff()) .registerView( InstrumentSelector.builder().setName("test").build(), View.builder() @@ -112,6 +119,10 @@ public OpenTelemetryClassicHistogram() { .setInstrumentationVersion("1.0.0") .build(); this.histogram = meter.histogramBuilder("test").setDescription("test").build(); + this.attributes = + Attributes.of( + AttributeKey.stringKey("path"), "/", + AttributeKey.stringKey("status"), "200"); } } @@ -119,6 +130,7 @@ public OpenTelemetryClassicHistogram() { public static class OpenTelemetryExponentialHistogram { final io.opentelemetry.api.metrics.DoubleHistogram histogram; + final Attributes attributes; public OpenTelemetryExponentialHistogram() { @@ -126,6 +138,7 @@ public OpenTelemetryExponentialHistogram() { SdkMeterProvider.builder() .registerMetricReader(InMemoryMetricReader.create()) .setResource(Resource.getDefault()) + .setExemplarFilter(ExemplarFilter.alwaysOff()) .registerView( InstrumentSelector.builder().setName("test").build(), View.builder() @@ -140,6 +153,89 @@ public OpenTelemetryExponentialHistogram() { .setInstrumentationVersion("1.0.0") .build(); this.histogram = meter.histogramBuilder("test").setDescription("test").build(); + this.attributes = + Attributes.of( + AttributeKey.stringKey("path"), "/", + AttributeKey.stringKey("status"), "200"); + } + } + + /** + * 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); } } @@ -198,7 +294,7 @@ public io.prometheus.client.Histogram simpleclient( public io.opentelemetry.api.metrics.DoubleHistogram openTelemetryClassic( RandomNumbers randomNumbers, OpenTelemetryClassicHistogram histogram) { for (int i = 0; i < randomNumbers.randomNumbers.length; i++) { - histogram.histogram.record(randomNumbers.randomNumbers[i]); + histogram.histogram.record(randomNumbers.randomNumbers[i], histogram.attributes); } return histogram.histogram; } @@ -207,6 +303,26 @@ public io.opentelemetry.api.metrics.DoubleHistogram openTelemetryClassic( @Threads(4) public io.opentelemetry.api.metrics.DoubleHistogram openTelemetryExponential( RandomNumbers randomNumbers, OpenTelemetryExponentialHistogram histogram) { + for (int i = 0; i < randomNumbers.randomNumbers.length; i++) { + histogram.histogram.record(randomNumbers.randomNumbers[i], histogram.attributes); + } + 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]); }