diff --git a/sdk/trace/src/jmh/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorCpuBenchmark.java b/sdk/trace/src/jmh/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorCpuBenchmark.java index 7756a752b82..b5f86793f72 100644 --- a/sdk/trace/src/jmh/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorCpuBenchmark.java +++ b/sdk/trace/src/jmh/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorCpuBenchmark.java @@ -28,6 +28,7 @@ import org.openjdk.jmh.annotations.TearDown; import org.openjdk.jmh.annotations.Threads; import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.BenchmarkParams; /* * Run this along with a profiler to measure the CPU usage of BatchSpanProcessor's exporter thread. @@ -47,7 +48,8 @@ public static class BenchmarkState { private long droppedSpans; @Setup(Level.Iteration) - public final void setup() { + public final void setup(BenchmarkParams params) { + numThreads = params.getThreads(); metricReader = InMemoryMetricReader.create(); MeterProvider meterProvider = SdkMeterProvider.builder().registerMetricReader(metricReader).build(); @@ -110,7 +112,6 @@ private static void doWork(BenchmarkState benchmarkState) { @OutputTimeUnit(TimeUnit.SECONDS) public void export_01Thread( BenchmarkState benchmarkState, @SuppressWarnings("unused") ThreadState threadState) { - benchmarkState.numThreads = 1; doWork(benchmarkState); } @@ -123,7 +124,6 @@ public void export_01Thread( @OutputTimeUnit(TimeUnit.SECONDS) public void export_02Thread( BenchmarkState benchmarkState, @SuppressWarnings("unused") ThreadState threadState) { - benchmarkState.numThreads = 2; doWork(benchmarkState); } @@ -136,7 +136,6 @@ public void export_02Thread( @OutputTimeUnit(TimeUnit.SECONDS) public void export_05Thread( BenchmarkState benchmarkState, @SuppressWarnings("unused") ThreadState threadState) { - benchmarkState.numThreads = 5; doWork(benchmarkState); } @@ -149,7 +148,6 @@ public void export_05Thread( @OutputTimeUnit(TimeUnit.SECONDS) public void export_10Thread( BenchmarkState benchmarkState, @SuppressWarnings("unused") ThreadState threadState) { - benchmarkState.numThreads = 10; doWork(benchmarkState); } @@ -162,7 +160,6 @@ public void export_10Thread( @OutputTimeUnit(TimeUnit.SECONDS) public void export_20Thread( BenchmarkState benchmarkState, @SuppressWarnings("unused") ThreadState threadState) { - benchmarkState.numThreads = 20; doWork(benchmarkState); } } diff --git a/sdk/trace/src/jmh/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorDroppedSpansBenchmark.java b/sdk/trace/src/jmh/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorDroppedSpansBenchmark.java index b5a438db88e..de580ccf4e6 100644 --- a/sdk/trace/src/jmh/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorDroppedSpansBenchmark.java +++ b/sdk/trace/src/jmh/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorDroppedSpansBenchmark.java @@ -24,6 +24,7 @@ import org.openjdk.jmh.annotations.TearDown; import org.openjdk.jmh.annotations.Threads; import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.BenchmarkParams; public class BatchSpanProcessorDroppedSpansBenchmark { @@ -36,9 +37,12 @@ public static class BenchmarkState { private long exportedSpans; private long droppedSpans; private int numThreads; + private int numIterations; @Setup(Level.Iteration) - public final void setup() { + public final void setup(BenchmarkParams params) { + numThreads = params.getThreads(); + numIterations = params.getMeasurement().getCount(); metricReader = InMemoryMetricReader.create(); MeterProvider meterProvider = SdkMeterProvider.builder().registerMetricReader(metricReader).build(); @@ -52,7 +56,7 @@ public final void setup() { public final void recordMetrics() { BatchSpanProcessorMetrics metrics = new BatchSpanProcessorMetrics(metricReader.collectAllMetrics(), numThreads); - dropRatio = metrics.dropRatio(); + dropRatio = metrics.dropRatio(numIterations); exportedSpans = metrics.exportedSpans(); droppedSpans = metrics.droppedSpans(); } @@ -64,7 +68,7 @@ public final void tearDown() { } @State(Scope.Thread) - @AuxCounters(AuxCounters.Type.OPERATIONS) + @AuxCounters(AuxCounters.Type.EVENTS) public static class ThreadState { BenchmarkState benchmarkState; @@ -95,7 +99,6 @@ public long droppedSpans() { @BenchmarkMode(Mode.Throughput) public void export( BenchmarkState benchmarkState, @SuppressWarnings("unused") ThreadState threadState) { - benchmarkState.numThreads = 5; benchmarkState.processor.onEnd( (ReadableSpan) benchmarkState.tracer.spanBuilder("span").startSpan()); } diff --git a/sdk/trace/src/jmh/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorMetrics.java b/sdk/trace/src/jmh/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorMetrics.java index 9a74d60070e..9d2107669da 100644 --- a/sdk/trace/src/jmh/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorMetrics.java +++ b/sdk/trace/src/jmh/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorMetrics.java @@ -5,12 +5,13 @@ package io.opentelemetry.sdk.trace.export; -import static io.opentelemetry.api.common.AttributeKey.stringKey; +import static io.opentelemetry.api.common.AttributeKey.booleanKey; import io.opentelemetry.sdk.metrics.data.LongPointData; import io.opentelemetry.sdk.metrics.data.MetricData; import java.util.Collection; import java.util.OptionalLong; +import org.openjdk.jmh.annotations.AuxCounters; public class BatchSpanProcessorMetrics { private final Collection allMetrics; @@ -21,13 +22,26 @@ public BatchSpanProcessorMetrics(Collection allMetrics, int numThrea this.numThreads = numThreads; } - public double dropRatio() { + /** + * Returns the share of dropped spans as a value in {@code [0, 1]}. + * + *

Only meaningful for benchmarks whose {@link AuxCounters} use {@link + * AuxCounters.Type#EVENTS}: JMH emits a {@code ScalarResult} with {@code AggregationPolicy.SUM}, + * which sums the aux counters across the {@code numThreads} thread-local {@code @State} instances + * and the {@code numIterations} measurement iterations. The raw {@code dropped / (exported + + * dropped)} is therefore inflated by {@code numThreads * numIterations}, and both factors are + * divided back out here so the value reported by JMH equals the per-iteration drop ratio. + * + *

For {@link AuxCounters.Type#OPERATIONS} JMH emits a {@code ThroughputResult} (rate per unit + * time) aggregated as a mean across iterations, so this method does not apply — the drop rate is + * read directly from {@link #droppedSpans()} and the ratio, if needed, is computed from the two + * rates. + */ + public double dropRatio(int numIterations) { long exported = getMetric(false); long dropped = getMetric(true); long total = exported + dropped; - // Due to peculiarities of JMH reporting we have to divide this by the number of the - // concurrent threads running the actual benchmark. - return total == 0 ? 0 : (double) dropped / total / numThreads; + return total == 0 ? 0.0 : (double) dropped / total / numThreads / numIterations; } public long exportedSpans() { @@ -39,14 +53,17 @@ public long droppedSpans() { } private long getMetric(boolean dropped) { - String labelValue = String.valueOf(dropped); OptionalLong value = allMetrics.stream() .filter(metricData -> metricData.getName().equals("processedSpans")) .filter(metricData -> !metricData.isEmpty()) .map(metricData -> metricData.getLongSumData().getPoints()) .flatMap(Collection::stream) - .filter(point -> labelValue.equals(point.getAttributes().get(stringKey("dropped")))) + .filter( + point -> { + Boolean attrDropped = point.getAttributes().get(booleanKey("dropped")); + return attrDropped != null && attrDropped == dropped; + }) .mapToLong(LongPointData::getValue) .findFirst(); return value.isPresent() ? value.getAsLong() : 0; diff --git a/sdk/trace/src/jmh/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorMultiThreadBenchmark.java b/sdk/trace/src/jmh/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorMultiThreadBenchmark.java index d8eabb090c3..c92c52f55fa 100644 --- a/sdk/trace/src/jmh/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorMultiThreadBenchmark.java +++ b/sdk/trace/src/jmh/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorMultiThreadBenchmark.java @@ -27,6 +27,7 @@ import org.openjdk.jmh.annotations.TearDown; import org.openjdk.jmh.annotations.Threads; import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.BenchmarkParams; @State(Scope.Benchmark) public class BatchSpanProcessorMultiThreadBenchmark { @@ -37,15 +38,19 @@ public static class BenchmarkState { private BatchSpanProcessor processor; private Tracer tracer; private int numThreads = 1; + private int numIterations = 1; @Param({"0"}) private int delayMs; + private double dropRatio; private long exportedSpans; private long droppedSpans; @Setup(Level.Iteration) - public final void setup() { + public final void setup(BenchmarkParams params) { + numThreads = params.getThreads(); + numIterations = params.getMeasurement().getCount(); collector = InMemoryMetricReader.create(); MeterProvider meterProvider = SdkMeterProvider.builder().registerMetricReader(collector).build(); @@ -59,6 +64,7 @@ public final void setup() { public final void recordMetrics() { BatchSpanProcessorMetrics metrics = new BatchSpanProcessorMetrics(collector.collectAllMetrics(), numThreads); + dropRatio = metrics.dropRatio(numIterations); exportedSpans = metrics.exportedSpans(); droppedSpans = metrics.droppedSpans(); processor.shutdown().join(10, TimeUnit.SECONDS); @@ -66,7 +72,7 @@ public final void recordMetrics() { } @State(Scope.Thread) - @AuxCounters(AuxCounters.Type.OPERATIONS) + @AuxCounters(AuxCounters.Type.EVENTS) public static class ThreadState { BenchmarkState benchmarkState; @@ -75,6 +81,10 @@ public final void recordMetrics(BenchmarkState benchmarkState) { this.benchmarkState = benchmarkState; } + public double dropRatio() { + return benchmarkState.dropRatio; + } + public long exportedSpans() { return benchmarkState.exportedSpans; } @@ -93,7 +103,6 @@ public long droppedSpans() { @OutputTimeUnit(TimeUnit.SECONDS) public void export_01Thread( BenchmarkState benchmarkState, @SuppressWarnings("unused") ThreadState threadState) { - benchmarkState.numThreads = 1; benchmarkState.processor.onEnd( (ReadableSpan) benchmarkState.tracer.spanBuilder("span").startSpan()); } @@ -107,7 +116,6 @@ public void export_01Thread( @OutputTimeUnit(TimeUnit.SECONDS) public void export_02Thread( BenchmarkState benchmarkState, @SuppressWarnings("unused") ThreadState threadState) { - benchmarkState.numThreads = 2; benchmarkState.processor.onEnd( (ReadableSpan) benchmarkState.tracer.spanBuilder("span").startSpan()); } @@ -121,7 +129,6 @@ public void export_02Thread( @OutputTimeUnit(TimeUnit.SECONDS) public void export_05Thread( BenchmarkState benchmarkState, @SuppressWarnings("unused") ThreadState threadState) { - benchmarkState.numThreads = 5; benchmarkState.processor.onEnd( (ReadableSpan) benchmarkState.tracer.spanBuilder("span").startSpan()); } @@ -135,7 +142,6 @@ public void export_05Thread( @OutputTimeUnit(TimeUnit.SECONDS) public void export_10Thread( BenchmarkState benchmarkState, @SuppressWarnings("unused") ThreadState threadState) { - benchmarkState.numThreads = 10; benchmarkState.processor.onEnd( (ReadableSpan) benchmarkState.tracer.spanBuilder("span").startSpan()); } @@ -149,7 +155,6 @@ public void export_10Thread( @OutputTimeUnit(TimeUnit.SECONDS) public void export_20Thread( BenchmarkState benchmarkState, @SuppressWarnings("unused") ThreadState threadState) { - benchmarkState.numThreads = 20; benchmarkState.processor.onEnd( (ReadableSpan) benchmarkState.tracer.spanBuilder("span").startSpan()); }