@@ -32,6 +32,11 @@ use opentelemetry_sdk::{
3232use pprof:: criterion:: { Output , PProfProfiler } ;
3333
3434fn criterion_benchmark ( c : & mut Criterion ) {
35+ // Benchmark to measure the effect of Arc<InstrumentationScope> optimization
36+ // This benchmark creates spans with multiple processors to demonstrate
37+ // the performance improvement when using Arc instead of cloning InstrumentationScope
38+ span_end_multiple_processors ( c) ;
39+
3540 trace_benchmark_group ( c, "span-creation-simple" , |tracer| {
3641 // Simple span creation
3742 // There is not ability to specify anything other than the name.
@@ -134,6 +139,43 @@ impl SpanExporter for VoidExporter {
134139 }
135140}
136141
142+ /// Benchmark span end with multiple processors
143+ ///
144+ /// This benchmark demonstrates the performance benefit of using Arc instead of cloning
145+ /// InstrumentationScope for each processor. The benefit scales with the number of processors:
146+ /// - With 1 processor: minimal difference (baseline)
147+ /// - With 3+ processors: significant improvement due to Arc::clone vs full clone
148+ fn span_end_multiple_processors ( c : & mut Criterion ) {
149+ let mut group = c. benchmark_group ( "span-end-multiple-processors" ) ;
150+
151+ // Test with different numbers of processors to show the scaling benefit
152+ for num_processors in [ 1 , 3 , 5 , 10 ] {
153+ group. bench_function ( format ! ( "{}-processors" , num_processors) , |b| {
154+ // Build provider with multiple simple exporters
155+ let mut builder =
156+ sdktrace:: SdkTracerProvider :: builder ( ) . with_sampler ( sdktrace:: Sampler :: AlwaysOn ) ;
157+
158+ for _ in 0 ..num_processors {
159+ builder = builder. with_simple_exporter ( VoidExporter ) ;
160+ }
161+
162+ let provider = builder. build ( ) ;
163+ let tracer = provider. tracer ( "benchmark-tracer" ) ;
164+
165+ b. iter ( || {
166+ // Create and immediately end a span
167+ // This triggers build_export_data which clones the instrumentation scope
168+ // With Arc, this is just an atomic increment per processor
169+ // Without Arc, this would be a full 120-byte clone per processor
170+ let mut span = tracer. start ( "test-span" ) ;
171+ span. end ( ) ;
172+ } ) ;
173+ } ) ;
174+ }
175+
176+ group. finish ( ) ;
177+ }
178+
137179fn trace_benchmark_group < F : Fn ( & sdktrace:: SdkTracer ) > ( c : & mut Criterion , name : & str , f : F ) {
138180 let mut group = c. benchmark_group ( name) ;
139181
0 commit comments