Skip to content

Conversation

@andrewlock
Copy link
Member

@andrewlock andrewlock commented Nov 27, 2025

Summary of changes

Replace ArraySegment<Span> with SpanCollection

Reason for change

ArraySegment<Span> is a wrapper around an array, and by design, always requires allocating an array.

However, if we look at the distribution of traces received for processing, we see that 50% of traces only have a single span.

Consequently, SpanCollection takes a similar approach to StringValues, in which it is an abstraction around either a single Span or a Span[]. This means we can avoid allocating the array entirely until we need to.

For small traces (with a single span), this saves 56 Bytes per scope/trace or ~8% of the basic trace size. For larger traces, SpanCollection and ArraySegment<Span> are essentially identical, so the allocation is the same.

Given SpanCollection (and ArraySegment actually) are readonly struct, also added in to the signatures (given that both structs are the same size and > pointer size).

The only practical way I could see to actually make SpanCollection pointer-sized is to remove the Count parameter. But that means we either need to allocate an "ArraySegment" wrapper around the Array, to hold the count, or we always allocate an array of the "correct" length. I explored the latter in a separate PR, using an array pool during the "builder" step, and then allocating an array of the correct size subsequently, but the allocation gains were marginal, and it didn't

Implementation details

The changes are essentially:

  • SpanCollection holds either a Span or a Span[] (or null)
  • We store this in the same field (much like StringValues does), as it reduces the size of the struct which brings small perf benefits
  • Pass the span around via in to reduce chance of defensive copies
  • Fix/replace uses of Moq which requires different usage for in/ref fields, and can't provide the same functionality as a stub

Test coverage

Added some unit tests for the implementation, but the important thing is the benchmarks. We see an 8-8.5% reduction in the allocations for create span/create scope:

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.SpanBenchmark.StartFinishScope‑net6.0 696 B 640 B -56 B -8.05%
Benchmarks.Trace.SpanBenchmark.StartFinishScope‑netcoreapp3.1 696 B 640 B -56 B -8.05%
Benchmarks.Trace.SpanBenchmark.StartFinishScope‑net472 658 B 602 B -56 B -8.51%
Benchmarks.Trace.SpanBenchmark.StartFinishSpan‑net472 578 B 522 B -56 B -9.69%
Benchmarks.Trace.SpanBenchmark.StartFinishSpan‑net6.0 576 B 520 B -56 B -9.72%
Benchmarks.Trace.SpanBenchmark.StartFinishSpan‑netcoreapp3.1 576 B 520 B -56 B -9.72%

Other benchmarks which create a single span see similar improvements.

Note that the two scope benchmark (added in #7869) shows essentially no change (as expected).

Other details

I tried a variety of variations on this approach:

  • Keep separate fields for Span and Span[]
    • Nicer as it's type safe again, but increases allocations (by a pointer) so prob not worth it as this is hot path
  • Don't pass via in
    • Slows things down slightly
  • Remove the Count field (and make SpanCollection pointer-sized)
    • Requires allocating exact-sized arrays, so not practical to handle array growth
  • Same as above, but use an array pool for the build stage, and then only allocate the fixed size on close
    • Does show improvements in allocation, but more complexity. May be worth considering (I'll create a separate PR for it)
  • Don't have a builder, just use an array pool + a Count field, and rely on reliably cleaning up the pooling,

https://datadoghq.atlassian.net/browse/LANGPLAT-841

@andrewlock andrewlock added the area:tracer The core tracer library (Datadog.Trace, does not include OpenTracing, native code, or integrations) label Nov 27, 2025
@andrewlock andrewlock requested review from a team as code owners November 27, 2025 10:47
@andrewlock andrewlock added the type:performance Performance, speed, latency, resource usage (CPU, memory) label Nov 27, 2025
@andrewlock andrewlock requested review from a team as code owners November 27, 2025 10:47
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@pr-commenter
Copy link

pr-commenter bot commented Nov 27, 2025

Benchmarks

Benchmarks Report for benchmark platform 🐌

Benchmarks for #7874 compared to master:

  • 2 benchmarks are slower, with geometric mean 1.168
  • 30 benchmarks have fewer allocations
  • 2 benchmarks have more allocations

The following thresholds were used for comparing the benchmark speeds:

  • Mann–Whitney U test with statistical test for significance of 5%
  • Only results indicating a difference greater than 10% and 0.3 ns are considered.

Allocation changes below 0.5% are ignored.

Benchmark details

Benchmarks.Trace.ActivityBenchmark - Same speed ✔️ Fewer allocations 🎉

Fewer allocations 🎉 in #7874

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.ActivityBenchmark.StartStopWithChild‑netcoreapp3.1 5.72 KB 5.59 KB -131 B -2.29%

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master StartStopWithChild net6.0 10.5μs 56.6ns 330ns 0 0 0 5.5 KB
master StartStopWithChild netcoreapp3.1 13.5μs 68.5ns 306ns 0 0 0 5.72 KB
master StartStopWithChild net472 21.8μs 79.6ns 298ns 0.87 0.217 0 6 KB
#7874 StartStopWithChild net6.0 10.9μs 59.3ns 325ns 0 0 0 5.51 KB
#7874 StartStopWithChild netcoreapp3.1 14.6μs 53.9ns 209ns 0 0 0 5.59 KB
#7874 StartStopWithChild net472 22.3μs 121ns 704ns 0.891 0.223 0 5.98 KB
Benchmarks.Trace.AgentWriterBenchmark - Same speed ✔️ More allocations ⚠️

More allocations ⚠️ in #7874

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.AgentWriterBenchmark.WriteAndFlushEnrichedTraces‑net472 3.26 KB 3.39 KB 128 B 3.92%

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master WriteAndFlushEnrichedTraces net6.0 1.25ms 206ns 770ns 0 0 0 2.7 KB
master WriteAndFlushEnrichedTraces netcoreapp3.1 1.39ms 79.6ns 308ns 0 0 0 2.7 KB
master WriteAndFlushEnrichedTraces net472 1.76ms 1.26μs 4.86μs 0 0 0 3.26 KB
#7874 WriteAndFlushEnrichedTraces net6.0 1.27ms 390ns 1.51μs 0 0 0 2.7 KB
#7874 WriteAndFlushEnrichedTraces netcoreapp3.1 1.37ms 722ns 2.8μs 0 0 0 2.7 KB
#7874 WriteAndFlushEnrichedTraces net472 1.73ms 887ns 3.44μs 0 0 0 3.39 KB
Benchmarks.Trace.Asm.AppSecBodyBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master AllCycleSimpleBody net6.0 1.09μs 6.08ns 39.9ns 0 0 0 1.22 KB
master AllCycleSimpleBody netcoreapp3.1 1.38μs 7.76ns 53.2ns 0 0 0 1.2 KB
master AllCycleSimpleBody net472 1μs 0.238ns 0.922ns 0.191 0 0 1.23 KB
master AllCycleMoreComplexBody net6.0 7.32μs 36.7ns 168ns 0 0 0 4.72 KB
master AllCycleMoreComplexBody netcoreapp3.1 8.88μs 46.5ns 237ns 0 0 0 4.62 KB
master AllCycleMoreComplexBody net472 7.7μs 4.23ns 16.4ns 0.731 0 0 4.74 KB
master ObjectExtractorSimpleBody net6.0 317ns 0.0977ns 0.366ns 0 0 0 280 B
master ObjectExtractorSimpleBody netcoreapp3.1 395ns 2.17ns 13.4ns 0 0 0 272 B
master ObjectExtractorSimpleBody net472 300ns 0.0108ns 0.0402ns 0.0439 0 0 281 B
master ObjectExtractorMoreComplexBody net6.0 6.34μs 29.4ns 118ns 0 0 0 3.78 KB
master ObjectExtractorMoreComplexBody netcoreapp3.1 7.82μs 36.6ns 142ns 0 0 0 3.69 KB
master ObjectExtractorMoreComplexBody net472 6.68μs 2.21ns 8.56ns 0.602 0 0 3.8 KB
#7874 AllCycleSimpleBody net6.0 1.11μs 2.8ns 10.8ns 0 0 0 1.22 KB
#7874 AllCycleSimpleBody netcoreapp3.1 1.47μs 4.72ns 18.3ns 0 0 0 1.2 KB
#7874 AllCycleSimpleBody net472 1.02μs 0.54ns 2.09ns 0.194 0 0 1.23 KB
#7874 AllCycleMoreComplexBody net6.0 7.23μs 35.8ns 139ns 0 0 0 4.72 KB
#7874 AllCycleMoreComplexBody netcoreapp3.1 9.17μs 46ns 206ns 0 0 0 4.62 KB
#7874 AllCycleMoreComplexBody net472 7.61μs 6.01ns 23.3ns 0.724 0 0 4.74 KB
#7874 ObjectExtractorSimpleBody net6.0 321ns 1.68ns 7.15ns 0 0 0 280 B
#7874 ObjectExtractorSimpleBody netcoreapp3.1 394ns 2.18ns 12.4ns 0 0 0 272 B
#7874 ObjectExtractorSimpleBody net472 296ns 0.0368ns 0.138ns 0.0432 0 0 281 B
#7874 ObjectExtractorMoreComplexBody net6.0 6.35μs 28.8ns 111ns 0 0 0 3.78 KB
#7874 ObjectExtractorMoreComplexBody netcoreapp3.1 7.87μs 37.2ns 154ns 0 0 0 3.69 KB
#7874 ObjectExtractorMoreComplexBody net472 6.7μs 4.53ns 17.5ns 0.571 0 0 3.8 KB
Benchmarks.Trace.Asm.AppSecEncoderBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EncodeArgs net6.0 76.3μs 299ns 1.12μs 0 0 0 32.4 KB
master EncodeArgs netcoreapp3.1 97.9μs 379ns 1.47μs 0 0 0 32.4 KB
master EncodeArgs net472 108μs 14ns 54.2ns 4.87 0 0 32.5 KB
master EncodeLegacyArgs net6.0 142μs 34.7ns 134ns 0 0 0 2.14 KB
master EncodeLegacyArgs netcoreapp3.1 198μs 26.2ns 98.1ns 0 0 0 2.14 KB
master EncodeLegacyArgs net472 263μs 42.9ns 166ns 0 0 0 2.14 KB
#7874 EncodeArgs net6.0 76.2μs 284ns 1.1μs 0 0 0 32.4 KB
#7874 EncodeArgs netcoreapp3.1 97.9μs 183ns 707ns 0 0 0 32.4 KB
#7874 EncodeArgs net472 108μs 18ns 69.9ns 4.89 0 0 32.5 KB
#7874 EncodeLegacyArgs net6.0 146μs 24.8ns 96.2ns 0 0 0 2.14 KB
#7874 EncodeLegacyArgs netcoreapp3.1 201μs 187ns 724ns 0 0 0 2.14 KB
#7874 EncodeLegacyArgs net472 262μs 23.4ns 90.7ns 0 0 0 2.14 KB
Benchmarks.Trace.Asm.AppSecWafBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master RunWafRealisticBenchmark net6.0 427μs 2.14μs 9.31μs 0 0 0 4.55 KB
master RunWafRealisticBenchmark netcoreapp3.1 464μs 1.58μs 5.9μs 0 0 0 4.48 KB
master RunWafRealisticBenchmark net472 496μs 231ns 834ns 0 0 0 0 b
master RunWafRealisticBenchmarkWithAttack net6.0 319μs 1.47μs 5.49μs 0 0 0 2.24 KB
master RunWafRealisticBenchmarkWithAttack netcoreapp3.1 347μs 1.93μs 13.6μs 0 0 0 2.22 KB
master RunWafRealisticBenchmarkWithAttack net472 368μs 493ns 1.78μs 0 0 0 0 b
#7874 RunWafRealisticBenchmark net6.0 432μs 1.37μs 4.92μs 0 0 0 4.55 KB
#7874 RunWafRealisticBenchmark netcoreapp3.1 465μs 3.47μs 32.9μs 0 0 0 4.48 KB
#7874 RunWafRealisticBenchmark net472 495μs 481ns 1.73μs 0 0 0 0 b
#7874 RunWafRealisticBenchmarkWithAttack net6.0 321μs 1.84μs 14.9μs 0 0 0 2.24 KB
#7874 RunWafRealisticBenchmarkWithAttack netcoreapp3.1 362μs 3.49μs 33.9μs 0 0 0 2.22 KB
#7874 RunWafRealisticBenchmarkWithAttack net472 371μs 352ns 1.27μs 0 0 0 0 b
Benchmarks.Trace.AspNetCoreBenchmark - Unknown 🤷 Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master SendRequest net6.0 84μs 75.5ns 292ns 0 0 0 19.03 KB
master SendRequest netcoreapp3.1 97μs 364ns 2.03μs 0 0 0 21.25 KB
master SendRequest net472 0ns 0ns 0ns 0 0 0 0 b
#7874 SendRequest net6.0 85.4μs 315ns 1.89μs 0 0 0 18.97 KB
#7874 SendRequest netcoreapp3.1 97μs 91.8ns 318ns 0 0 0 21.18 KB
#7874 SendRequest net472 0ns 0ns 0ns 0 0 0 0 b
Benchmarks.Trace.CharSliceBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master OriginalCharSlice net6.0 1.91ms 1.86μs 7.21μs 0 0 0 640 KB
master OriginalCharSlice netcoreapp3.1 3.93ms 877ns 3.39μs 0 0 0 640.05 KB
master OriginalCharSlice net472 2.58ms 442ns 1.65μs 0 0 0 638.98 KB
master OptimizedCharSlice net6.0 1.45ms 3.25μs 12.6μs 0 0 0 0 b
master OptimizedCharSlice netcoreapp3.1 2.73ms 996ns 3.45μs 0 0 0 0 b
master OptimizedCharSlice net472 1.95ms 957ns 3.58μs 0 0 0 0 b
master OptimizedCharSliceWithPool net6.0 1.05ms 691ns 2.68μs 0 0 0 0 b
master OptimizedCharSliceWithPool netcoreapp3.1 1.85ms 1.99μs 7.7μs 0 0 0 0 b
master OptimizedCharSliceWithPool net472 1.16ms 710ns 2.75μs 0 0 0 0 b
#7874 OriginalCharSlice net6.0 2.02ms 2.02μs 7.58μs 0 0 0 640 KB
#7874 OriginalCharSlice netcoreapp3.1 3.9ms 2.55μs 9.19μs 0 0 0 640.05 KB
#7874 OriginalCharSlice net472 2.6ms 757ns 2.93μs 0 0 0 638.98 KB
#7874 OptimizedCharSlice net6.0 1.44ms 894ns 3.46μs 0 0 0 0 b
#7874 OptimizedCharSlice netcoreapp3.1 2.75ms 1.55μs 6μs 0 0 0 0 b
#7874 OptimizedCharSlice net472 1.9ms 774ns 3μs 0 0 0 0 b
#7874 OptimizedCharSliceWithPool net6.0 1.09ms 651ns 2.44μs 0 0 0 0 b
#7874 OptimizedCharSliceWithPool netcoreapp3.1 1.88ms 1.59μs 6.16μs 0 0 0 0 b
#7874 OptimizedCharSliceWithPool net472 1.17ms 559ns 2.09μs 0 0 0 0 b
Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark - Slower ⚠️ More allocations ⚠️

Slower ⚠️ in #7874

Benchmark diff/base Base Median (ns) Diff Median (ns) Modality
Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark.WriteAndFlushEnrichedTraces‑netcoreapp3.1 1.178 690,077.92 812,952.94

More allocations ⚠️ in #7874

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark.WriteAndFlushEnrichedTraces‑net6.0 41.68 KB 42 KB 318 B 0.76%

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master WriteAndFlushEnrichedTraces net6.0 761μs 1.44μs 5.57μs 0 0 0 41.68 KB
master WriteAndFlushEnrichedTraces netcoreapp3.1 700μs 3.64μs 17.8μs 0 0 0 41.8 KB
master WriteAndFlushEnrichedTraces net472 892μs 3.52μs 13.6μs 4.46 0 0 55.79 KB
#7874 WriteAndFlushEnrichedTraces net6.0 747μs 1.43μs 5.16μs 0 0 0 42 KB
#7874 WriteAndFlushEnrichedTraces netcoreapp3.1 814μs 1.91μs 6.9μs 0 0 0 41.89 KB
#7874 WriteAndFlushEnrichedTraces net472 868μs 3.85μs 15.4μs 4.46 0 0 55.87 KB
Benchmarks.Trace.DbCommandBenchmark - Same speed ✔️ Fewer allocations 🎉

Fewer allocations 🎉 in #7874

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.DbCommandBenchmark.ExecuteNonQuery‑net6.0 1.02 KB 968 B -56 B -5.47%
Benchmarks.Trace.DbCommandBenchmark.ExecuteNonQuery‑netcoreapp3.1 1.02 KB 960 B -56 B -5.51%
Benchmarks.Trace.DbCommandBenchmark.ExecuteNonQuery‑net472 987 B 931 B -56 B -5.67%

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master ExecuteNonQuery net6.0 1.86μs 7.27ns 28.2ns 0 0 0 1.02 KB
master ExecuteNonQuery netcoreapp3.1 2.57μs 6.77ns 26.2ns 0 0 0 1.02 KB
master ExecuteNonQuery net472 2.79μs 3.48ns 13.5ns 0.15 0 0 987 B
#7874 ExecuteNonQuery net6.0 1.98μs 2.89ns 10.8ns 0 0 0 968 B
#7874 ExecuteNonQuery netcoreapp3.1 2.52μs 9.81ns 36.7ns 0 0 0 960 B
#7874 ExecuteNonQuery net472 2.69μs 1.77ns 6.64ns 0.135 0 0 931 B
Benchmarks.Trace.ElasticsearchBenchmark - Same speed ✔️ Fewer allocations 🎉

Fewer allocations 🎉 in #7874

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.ElasticsearchBenchmark.CallElasticsearchAsync‑netcoreapp3.1 1.07 KB 1.02 KB -56 B -5.22%
Benchmarks.Trace.ElasticsearchBenchmark.CallElasticsearchAsync‑net472 1.07 KB 1.01 KB -56 B -5.25%
Benchmarks.Trace.ElasticsearchBenchmark.CallElasticsearch‑netcoreapp3.1 1.02 KB 968 B -56 B -5.47%
Benchmarks.Trace.ElasticsearchBenchmark.CallElasticsearch‑net472 1.01 KB 955 B -56 B -5.54%
Benchmarks.Trace.ElasticsearchBenchmark.CallElasticsearch‑net6.0 1.01 KB 952 B -56 B -5.56%
Benchmarks.Trace.ElasticsearchBenchmark.CallElasticsearchAsync‑net6.0 984 B 928 B -56 B -5.69%

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master CallElasticsearch net6.0 1.67μs 8.33ns 36.3ns 0 0 0 1.01 KB
master CallElasticsearch netcoreapp3.1 2.27μs 9.56ns 37ns 0 0 0 1.02 KB
master CallElasticsearch net472 3.4μs 3.1ns 11.6ns 0.154 0 0 1.01 KB
master CallElasticsearchAsync net6.0 1.76μs 8.62ns 35.5ns 0 0 0 984 B
master CallElasticsearchAsync netcoreapp3.1 2.46μs 10.8ns 41.9ns 0 0 0 1.07 KB
master CallElasticsearchAsync net472 3.55μs 1.58ns 5.9ns 0.159 0 0 1.07 KB
#7874 CallElasticsearch net6.0 1.65μs 7.19ns 27.9ns 0 0 0 952 B
#7874 CallElasticsearch netcoreapp3.1 2.29μs 1.67ns 6.45ns 0 0 0 968 B
#7874 CallElasticsearch net472 3.26μs 3.16ns 11.8ns 0.147 0 0 955 B
#7874 CallElasticsearchAsync net6.0 1.82μs 9.64ns 47.2ns 0 0 0 928 B
#7874 CallElasticsearchAsync netcoreapp3.1 2.4μs 9.92ns 38.4ns 0 0 0 1.02 KB
#7874 CallElasticsearchAsync net472 3.45μs 2.56ns 9.93ns 0.154 0 0 1.01 KB
Benchmarks.Trace.GraphQLBenchmark - Same speed ✔️ Fewer allocations 🎉

Fewer allocations 🎉 in #7874

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.GraphQLBenchmark.ExecuteAsync‑netcoreapp3.1 952 B 896 B -56 B -5.88%
Benchmarks.Trace.GraphQLBenchmark.ExecuteAsync‑net6.0 953 B 896 B -57 B -5.98%
Benchmarks.Trace.GraphQLBenchmark.ExecuteAsync‑net472 915 B 859 B -56 B -6.12%

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master ExecuteAsync net6.0 1.91μs 9.42ns 38.8ns 0 0 0 953 B
master ExecuteAsync netcoreapp3.1 2.5μs 7.36ns 28.5ns 0 0 0 952 B
master ExecuteAsync net472 2.63μs 2.29ns 8.86ns 0.144 0 0 915 B
#7874 ExecuteAsync net6.0 1.89μs 3.9ns 14.6ns 0 0 0 896 B
#7874 ExecuteAsync netcoreapp3.1 2.47μs 6.48ns 25.1ns 0 0 0 896 B
#7874 ExecuteAsync net472 2.58μs 2.24ns 8.66ns 0.129 0 0 859 B
Benchmarks.Trace.HttpClientBenchmark - Same speed ✔️ Fewer allocations 🎉

Fewer allocations 🎉 in #7874

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.HttpClientBenchmark.SendAsync‑net472 3.14 KB 3.08 KB -56 B -1.79%
Benchmarks.Trace.HttpClientBenchmark.SendAsync‑netcoreapp3.1 2.89 KB 2.83 KB -56 B -1.94%
Benchmarks.Trace.HttpClientBenchmark.SendAsync‑net6.0 2.34 KB 2.29 KB -56 B -2.39%

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master SendAsync net6.0 6.89μs 23.4ns 90.8ns 0 0 0 2.34 KB
master SendAsync netcoreapp3.1 8.46μs 24.9ns 89.7ns 0 0 0 2.89 KB
master SendAsync net472 12.2μs 9.27ns 34.7ns 0.489 0 0 3.14 KB
#7874 SendAsync net6.0 7.09μs 31.4ns 122ns 0 0 0 2.29 KB
#7874 SendAsync netcoreapp3.1 8.44μs 18.9ns 73.4ns 0 0 0 2.83 KB
#7874 SendAsync net472 12μs 7.81ns 30.2ns 0.48 0 0 3.08 KB
Benchmarks.Trace.Iast.StringAspectsBenchmark - Slower ⚠️ Fewer allocations 🎉

Slower ⚠️ in #7874

Benchmark diff/base Base Median (ns) Diff Median (ns) Modality
Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatAspectBenchmark‑netcoreapp3.1 1.158 419,750.00 486,100.00 several?

Fewer allocations 🎉 in #7874

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatAspectBenchmark‑netcoreapp3.1 257.52 KB 254.78 KB -2.74 KB -1.06%
Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatAspectBenchmark‑net6.0 273.92 KB 247.62 KB -26.3 KB -9.60%

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master StringConcatBenchmark net6.0 44.9μs 266ns 2.39μs 0 0 0 42.51 KB
master StringConcatBenchmark netcoreapp3.1 50.7μs 327ns 3.09μs 0 0 0 42.54 KB
master StringConcatBenchmark net472 56.4μs 290ns 1.3μs 0 0 0 49.15 KB
master StringConcatAspectBenchmark net6.0 485μs 2.34μs 9.37μs 0 0 0 273.92 KB
master StringConcatAspectBenchmark netcoreapp3.1 434μs 5.13μs 50.3μs 0 0 0 257.52 KB
master StringConcatAspectBenchmark net472 411μs 2.37μs 18.3μs 0 0 0 270.34 KB
#7874 StringConcatBenchmark net6.0 44.8μs 251ns 1.71μs 0 0 0 42.51 KB
#7874 StringConcatBenchmark netcoreapp3.1 50.3μs 232ns 1.29μs 0 0 0 42.54 KB
#7874 StringConcatBenchmark net472 57.3μs 142ns 512ns 0 0 0 49.15 KB
#7874 StringConcatAspectBenchmark net6.0 447μs 2.11μs 7.89μs 0 0 0 247.62 KB
#7874 StringConcatAspectBenchmark netcoreapp3.1 488μs 1.83μs 7.96μs 0 0 0 254.78 KB
#7874 StringConcatAspectBenchmark net472 406μs 2.1μs 9.63μs 0 0 0 270.34 KB
Benchmarks.Trace.ILoggerBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EnrichedLog net6.0 2.71μs 13.2ns 57.7ns 0 0 0 1.69 KB
master EnrichedLog netcoreapp3.1 3.53μs 4.87ns 18.9ns 0 0 0 1.7 KB
master EnrichedLog net472 3.85μs 2.27ns 8.81ns 0.251 0 0 1.6 KB
#7874 EnrichedLog net6.0 2.73μs 13.1ns 52.2ns 0 0 0 1.69 KB
#7874 EnrichedLog netcoreapp3.1 3.67μs 1.99ns 7.45ns 0 0 0 1.7 KB
#7874 EnrichedLog net472 3.83μs 3.94ns 15.2ns 0.247 0 0 1.6 KB
Benchmarks.Trace.Log4netBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EnrichedLog net6.0 124μs 53.6ns 186ns 0 0 0 4.31 KB
master EnrichedLog netcoreapp3.1 129μs 199ns 718ns 0 0 0 4.31 KB
master EnrichedLog net472 168μs 150ns 580ns 0 0 0 4.51 KB
#7874 EnrichedLog net6.0 124μs 125ns 483ns 0 0 0 4.31 KB
#7874 EnrichedLog netcoreapp3.1 130μs 257ns 961ns 0 0 0 4.31 KB
#7874 EnrichedLog net472 172μs 144ns 559ns 0 0 0 4.51 KB
Benchmarks.Trace.NLogBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EnrichedLog net6.0 5.15μs 20.2ns 78.2ns 0 0 0 2.24 KB
master EnrichedLog netcoreapp3.1 6.95μs 20.3ns 78.6ns 0 0 0 2.26 KB
master EnrichedLog net472 7.55μs 8.84ns 34.2ns 0.3 0 0 2.05 KB
#7874 EnrichedLog net6.0 5.04μs 14.2ns 53ns 0 0 0 2.24 KB
#7874 EnrichedLog netcoreapp3.1 6.76μs 15.8ns 56.9ns 0 0 0 2.26 KB
#7874 EnrichedLog net472 7.7μs 6.86ns 26.6ns 0.307 0 0 2.05 KB
Benchmarks.Trace.RedisBenchmark - Same speed ✔️ Fewer allocations 🎉

Fewer allocations 🎉 in #7874

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.RedisBenchmark.SendReceive‑netcoreapp3.1 1.19 KB 1.14 KB -56 B -4.70%
Benchmarks.Trace.RedisBenchmark.SendReceive‑net6.0 1.18 KB 1.12 KB -56 B -4.76%
Benchmarks.Trace.RedisBenchmark.SendReceive‑net472 1.17 KB 1.12 KB -56 B -4.78%

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master SendReceive net6.0 2μs 0.614ns 2.38ns 0 0 0 1.18 KB
master SendReceive netcoreapp3.1 2.65μs 12.8ns 54.2ns 0 0 0 1.19 KB
master SendReceive net472 2.95μs 2.31ns 8.94ns 0.177 0 0 1.17 KB
#7874 SendReceive net6.0 1.92μs 6.67ns 25.8ns 0 0 0 1.12 KB
#7874 SendReceive netcoreapp3.1 2.67μs 12.3ns 47.5ns 0 0 0 1.14 KB
#7874 SendReceive net472 2.86μs 5.16ns 20ns 0.169 0 0 1.12 KB
Benchmarks.Trace.SerilogBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EnrichedLog net6.0 4.34μs 4.31ns 16.7ns 0 0 0 1.58 KB
master EnrichedLog netcoreapp3.1 5.44μs 16.8ns 65.1ns 0 0 0 1.63 KB
master EnrichedLog net472 6.59μs 11.4ns 44ns 0.294 0 0 2.03 KB
#7874 EnrichedLog net6.0 4.42μs 4.44ns 16.6ns 0 0 0 1.58 KB
#7874 EnrichedLog netcoreapp3.1 5.85μs 17.9ns 69.4ns 0 0 0 1.63 KB
#7874 EnrichedLog net472 6.52μs 7.46ns 27.9ns 0.295 0 0 2.03 KB
Benchmarks.Trace.SpanBenchmark - Same speed ✔️ Fewer allocations 🎉

Fewer allocations 🎉 in #7874

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.SpanBenchmark.StartFinishScope‑net6.0 696 B 640 B -56 B -8.05%
Benchmarks.Trace.SpanBenchmark.StartFinishScope‑netcoreapp3.1 696 B 640 B -56 B -8.05%
Benchmarks.Trace.SpanBenchmark.StartFinishScope‑net472 658 B 602 B -56 B -8.51%
Benchmarks.Trace.SpanBenchmark.StartFinishSpan‑net472 578 B 522 B -56 B -9.69%
Benchmarks.Trace.SpanBenchmark.StartFinishSpan‑net6.0 576 B 520 B -56 B -9.72%
Benchmarks.Trace.SpanBenchmark.StartFinishSpan‑netcoreapp3.1 576 B 520 B -56 B -9.72%

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master StartFinishSpan net6.0 798ns 4.05ns 17.7ns 0 0 0 576 B
master StartFinishSpan netcoreapp3.1 975ns 5.14ns 21.8ns 0 0 0 576 B
master StartFinishSpan net472 902ns 0.0976ns 0.365ns 0.0907 0 0 578 B
master StartFinishScope net6.0 946ns 3.67ns 13.7ns 0 0 0 696 B
master StartFinishScope netcoreapp3.1 1.16μs 5.79ns 24.6ns 0 0 0 696 B
master StartFinishScope net472 1.12μs 0.553ns 2.14ns 0.101 0 0 658 B
master StartFinishTwoScopes net6.0 1.78μs 2.92ns 11.3ns 0 0 0 1.19 KB
master StartFinishTwoScopes netcoreapp3.1 2.19μs 11.3ns 55.4ns 0 0 0 1.19 KB
master StartFinishTwoScopes net472 2.17μs 2.55ns 9.87ns 0.162 0 0 1.08 KB
#7874 StartFinishSpan net6.0 769ns 3.69ns 16.1ns 0 0 0 520 B
#7874 StartFinishSpan netcoreapp3.1 948ns 4.91ns 22.5ns 0 0 0 520 B
#7874 StartFinishSpan net472 890ns 0.448ns 1.74ns 0.0799 0 0 522 B
#7874 StartFinishScope net6.0 918ns 1.26ns 4.87ns 0 0 0 640 B
#7874 StartFinishScope netcoreapp3.1 1.13μs 5.68ns 25.4ns 0 0 0 640 B
#7874 StartFinishScope net472 1.11μs 0.791ns 2.96ns 0.0947 0 0 602 B
#7874 StartFinishTwoScopes net6.0 1.79μs 9.53ns 47.6ns 0 0 0 1.19 KB
#7874 StartFinishTwoScopes netcoreapp3.1 2.25μs 8.56ns 33.2ns 0 0 0 1.19 KB
#7874 StartFinishTwoScopes net472 2.13μs 1.77ns 6.85ns 0.171 0 0 1.08 KB
Benchmarks.Trace.TraceAnnotationsBenchmark - Same speed ✔️ Fewer allocations 🎉

Fewer allocations 🎉 in #7874

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.TraceAnnotationsBenchmark.RunOnMethodBegin‑net6.0 696 B 640 B -56 B -8.05%
Benchmarks.Trace.TraceAnnotationsBenchmark.RunOnMethodBegin‑netcoreapp3.1 696 B 640 B -56 B -8.05%
Benchmarks.Trace.TraceAnnotationsBenchmark.RunOnMethodBegin‑net472 658 B 602 B -56 B -8.51%

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master RunOnMethodBegin net6.0 1.12μs 5.98ns 31.6ns 0 0 0 696 B
master RunOnMethodBegin netcoreapp3.1 1.42μs 7.24ns 33.2ns 0 0 0 696 B
master RunOnMethodBegin net472 1.49μs 3.84ns 14.9ns 0.098 0 0 658 B
#7874 RunOnMethodBegin net6.0 1.05μs 4.96ns 20.5ns 0 0 0 640 B
#7874 RunOnMethodBegin netcoreapp3.1 1.4μs 6.29ns 22.7ns 0 0 0 640 B
#7874 RunOnMethodBegin net472 1.44μs 0.329ns 1.27ns 0.0938 0 0 602 B

@dd-trace-dotnet-ci-bot
Copy link

dd-trace-dotnet-ci-bot bot commented Nov 27, 2025

Execution-Time Benchmarks Report ⏱️

Execution-time results for samples comparing This PR (7874) and master.

✅ No regressions detected - check the details below

Full Metrics Comparison

FakeDbCommand

Metric Master (Mean ± 95% CI) Current (Mean ± 95% CI) Change Status
.NET Framework 4.8 - Baseline
duration75.51 ± (75.51 - 76.16) ms75.53 ± (75.67 - 76.34) ms+0.0%✅⬆️
.NET Framework 4.8 - Bailout
duration79.71 ± (79.41 - 80.04) ms79.63 ± (79.55 - 80.12) ms-0.1%
.NET Framework 4.8 - CallTarget+Inlining+NGEN
duration1059.05 ± (1059.60 - 1068.42) ms1070.65 ± (1072.06 - 1082.70) ms+1.1%✅⬆️
.NET Core 3.1 - Baseline
process.internal_duration_ms22.87 ± (22.80 - 22.95) ms22.85 ± (22.78 - 22.93) ms-0.1%
process.time_to_main_ms86.29 ± (85.99 - 86.59) ms86.43 ± (86.13 - 86.73) ms+0.2%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed10.90 ± (10.90 - 10.91) MB10.91 ± (10.91 - 10.92) MB+0.1%✅⬆️
runtime.dotnet.threads.count12 ± (12 - 12)12 ± (12 - 12)+0.0%
.NET Core 3.1 - Bailout
process.internal_duration_ms22.71 ± (22.65 - 22.77) ms22.79 ± (22.73 - 22.86) ms+0.4%✅⬆️
process.time_to_main_ms87.36 ± (87.01 - 87.71) ms87.85 ± (87.50 - 88.20) ms+0.6%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed10.95 ± (10.94 - 10.95) MB10.95 ± (10.94 - 10.95) MB-0.0%
runtime.dotnet.threads.count13 ± (13 - 13)13 ± (13 - 13)+0.0%
.NET Core 3.1 - CallTarget+Inlining+NGEN
process.internal_duration_ms220.19 ± (218.68 - 221.71) ms220.51 ± (219.22 - 221.81) ms+0.1%✅⬆️
process.time_to_main_ms499.39 ± (498.24 - 500.53) ms497.17 ± (496.16 - 498.18) ms-0.4%
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed47.87 ± (47.85 - 47.89) MB47.90 ± (47.88 - 47.92) MB+0.1%✅⬆️
runtime.dotnet.threads.count28 ± (28 - 28)28 ± (28 - 28)+0.0%
.NET 6 - Baseline
process.internal_duration_ms21.80 ± (21.74 - 21.86) ms21.68 ± (21.61 - 21.74) ms-0.6%
process.time_to_main_ms76.20 ± (75.93 - 76.47) ms76.33 ± (75.99 - 76.66) ms+0.2%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed10.59 ± (10.59 - 10.59) MB10.63 ± (10.63 - 10.63) MB+0.3%✅⬆️
runtime.dotnet.threads.count10 ± (10 - 10)10 ± (10 - 10)+0.0%
.NET 6 - Bailout
process.internal_duration_ms21.78 ± (21.71 - 21.85) ms21.91 ± (21.84 - 21.99) ms+0.6%✅⬆️
process.time_to_main_ms77.80 ± (77.49 - 78.10) ms78.36 ± (77.99 - 78.73) ms+0.7%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed10.64 ± (10.64 - 10.64) MB10.66 ± (10.66 - 10.67) MB+0.2%✅⬆️
runtime.dotnet.threads.count11 ± (11 - 11)11 ± (11 - 11)+0.0%
.NET 6 - CallTarget+Inlining+NGEN
process.internal_duration_ms210.02 ± (208.88 - 211.16) ms211.85 ± (210.81 - 212.89) ms+0.9%✅⬆️
process.time_to_main_ms465.92 ± (464.77 - 467.07) ms468.84 ± (467.84 - 469.83) ms+0.6%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed48.14 ± (48.11 - 48.17) MB48.09 ± (48.07 - 48.11) MB-0.1%
runtime.dotnet.threads.count28 ± (28 - 28)28 ± (28 - 28)+0.0%✅⬆️
.NET 8 - Baseline
process.internal_duration_ms19.67 ± (19.61 - 19.73) ms19.88 ± (19.81 - 19.95) ms+1.0%✅⬆️
process.time_to_main_ms74.47 ± (74.15 - 74.80) ms75.37 ± (75.06 - 75.69) ms+1.2%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed7.64 ± (7.64 - 7.65) MB7.65 ± (7.65 - 7.66) MB+0.1%✅⬆️
runtime.dotnet.threads.count10 ± (10 - 10)10 ± (10 - 10)+0.0%
.NET 8 - Bailout
process.internal_duration_ms20.05 ± (19.97 - 20.12) ms19.83 ± (19.76 - 19.89) ms-1.1%
process.time_to_main_ms78.63 ± (78.21 - 79.06) ms76.68 ± (76.32 - 77.05) ms-2.5%
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed7.69 ± (7.69 - 7.70) MB7.72 ± (7.71 - 7.73) MB+0.4%✅⬆️
runtime.dotnet.threads.count11 ± (11 - 11)11 ± (11 - 11)+0.0%
.NET 8 - CallTarget+Inlining+NGEN
process.internal_duration_ms194.08 ± (192.88 - 195.27) ms194.04 ± (193.12 - 194.97) ms-0.0%
process.time_to_main_ms456.43 ± (455.31 - 457.55) ms455.37 ± (454.23 - 456.51) ms-0.2%
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed36.34 ± (36.30 - 36.38) MB36.48 ± (36.43 - 36.52) MB+0.4%✅⬆️
runtime.dotnet.threads.count27 ± (27 - 27)27 ± (27 - 27)-0.1%

HttpMessageHandler

Metric Master (Mean ± 95% CI) Current (Mean ± 95% CI) Change Status
.NET Framework 4.8 - Baseline
duration192.38 ± (192.44 - 193.25) ms192.53 ± (192.47 - 193.31) ms+0.1%✅⬆️
.NET Framework 4.8 - Bailout
duration196.53 ± (196.38 - 196.89) ms196.27 ± (196.31 - 196.87) ms-0.1%
.NET Framework 4.8 - CallTarget+Inlining+NGEN
duration1109.78 ± (1112.40 - 1119.95) ms1111.71 ± (1112.33 - 1119.81) ms+0.2%✅⬆️
.NET Core 3.1 - Baseline
process.internal_duration_ms187.76 ± (187.35 - 188.16) ms187.91 ± (187.58 - 188.24) ms+0.1%✅⬆️
process.time_to_main_ms80.58 ± (80.38 - 80.79) ms80.40 ± (80.23 - 80.56) ms-0.2%
runtime.dotnet.exceptions.count3 ± (3 - 3)3 ± (3 - 3)+0.0%
runtime.dotnet.mem.committed16.09 ± (16.06 - 16.11) MB16.14 ± (16.11 - 16.17) MB+0.4%✅⬆️
runtime.dotnet.threads.count20 ± (19 - 20)20 ± (19 - 20)-0.0%
.NET Core 3.1 - Bailout
process.internal_duration_ms187.18 ± (186.86 - 187.50) ms187.14 ± (186.73 - 187.54) ms-0.0%
process.time_to_main_ms81.88 ± (81.75 - 82.00) ms81.97 ± (81.81 - 82.13) ms+0.1%✅⬆️
runtime.dotnet.exceptions.count3 ± (3 - 3)3 ± (3 - 3)+0.0%
runtime.dotnet.mem.committed16.14 ± (16.12 - 16.17) MB16.17 ± (16.14 - 16.20) MB+0.1%✅⬆️
runtime.dotnet.threads.count21 ± (20 - 21)21 ± (20 - 21)+0.1%✅⬆️
.NET Core 3.1 - CallTarget+Inlining+NGEN
process.internal_duration_ms399.72 ± (396.96 - 402.48) ms397.23 ± (394.76 - 399.71) ms-0.6%
process.time_to_main_ms473.05 ± (472.44 - 473.65) ms471.59 ± (471.00 - 472.18) ms-0.3%
runtime.dotnet.exceptions.count3 ± (3 - 3)3 ± (3 - 3)+0.0%
runtime.dotnet.mem.committed58.68 ± (58.56 - 58.81) MB58.58 ± (58.43 - 58.73) MB-0.2%
runtime.dotnet.threads.count29 ± (29 - 29)29 ± (29 - 30)+0.0%✅⬆️
.NET 6 - Baseline
process.internal_duration_ms192.79 ± (192.47 - 193.12) ms191.45 ± (191.14 - 191.75) ms-0.7%
process.time_to_main_ms69.96 ± (69.80 - 70.13) ms69.82 ± (69.66 - 69.98) ms-0.2%
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed16.22 ± (16.11 - 16.34) MB16.22 ± (16.09 - 16.34) MB-0.1%
runtime.dotnet.threads.count19 ± (19 - 19)18 ± (18 - 18)-3.0%
.NET 6 - Bailout
process.internal_duration_ms191.29 ± (191.04 - 191.54) ms190.86 ± (190.62 - 191.10) ms-0.2%
process.time_to_main_ms70.82 ± (70.73 - 70.91) ms70.61 ± (70.52 - 70.70) ms-0.3%
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed16.10 ± (15.96 - 16.24) MB16.18 ± (16.04 - 16.32) MB+0.5%✅⬆️
runtime.dotnet.threads.count20 ± (19 - 20)19 ± (19 - 20)-1.5%
.NET 6 - CallTarget+Inlining+NGEN
process.internal_duration_ms409.55 ± (407.01 - 412.10) ms411.62 ± (409.34 - 413.89) ms+0.5%✅⬆️
process.time_to_main_ms441.10 ± (440.35 - 441.85) ms440.49 ± (439.96 - 441.03) ms-0.1%
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed58.95 ± (58.78 - 59.13) MB59.10 ± (58.97 - 59.23) MB+0.2%✅⬆️
runtime.dotnet.threads.count30 ± (29 - 30)30 ± (30 - 30)+0.1%✅⬆️
.NET 8 - Baseline
process.internal_duration_ms190.32 ± (190.02 - 190.62) ms189.75 ± (189.41 - 190.09) ms-0.3%
process.time_to_main_ms69.33 ± (69.16 - 69.49) ms69.42 ± (69.21 - 69.63) ms+0.1%✅⬆️
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed11.81 ± (11.78 - 11.83) MB11.74 ± (11.72 - 11.77) MB-0.5%
runtime.dotnet.threads.count18 ± (18 - 18)18 ± (18 - 18)-0.2%
.NET 8 - Bailout
process.internal_duration_ms190.13 ± (189.86 - 190.39) ms188.98 ± (188.74 - 189.22) ms-0.6%
process.time_to_main_ms70.41 ± (70.29 - 70.52) ms70.28 ± (70.19 - 70.37) ms-0.2%
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed11.80 ± (11.77 - 11.84) MB11.71 ± (11.63 - 11.80) MB-0.8%
runtime.dotnet.threads.count19 ± (19 - 19)19 ± (18 - 19)-3.5%
.NET 8 - CallTarget+Inlining+NGEN
process.internal_duration_ms367.77 ± (366.27 - 369.27) ms365.00 ± (363.67 - 366.34) ms-0.8%
process.time_to_main_ms429.98 ± (429.24 - 430.72) ms428.95 ± (428.19 - 429.70) ms-0.2%
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed47.88 ± (47.85 - 47.91) MB47.89 ± (47.86 - 47.92) MB+0.0%✅⬆️
runtime.dotnet.threads.count29 ± (29 - 29)29 ± (29 - 29)-0.7%
Comparison explanation

Execution-time benchmarks measure the whole time it takes to execute a program, and are intended to measure the one-off costs. Cases where the execution time results for the PR are worse than latest master results are highlighted in **red**. The following thresholds were used for comparing the execution times:

  • Welch test with statistical test for significance of 5%
  • Only results indicating a difference greater than 5% and 5 ms are considered.

Note that these results are based on a single point-in-time result for each branch. For full results, see the dashboard.

Graphs show the p99 interval based on the mean and StdDev of the test run, as well as the mean value of the run (shown as a diamond below the graph).

Duration charts
FakeDbCommand (.NET Framework 4.8)
gantt
    title Execution time (ms) FakeDbCommand (.NET Framework 4.8)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (7874) - mean (76ms)  : 71, 81
    master - mean (76ms)  : 71, 81

    section Bailout
    This PR (7874) - mean (80ms)  : 75, 84
    master - mean (80ms)  : 75, 85

    section CallTarget+Inlining+NGEN
    This PR (7874) - mean (1,077ms)  : 995, 1160
    master - mean (1,064ms)  : 998, 1130

Loading
FakeDbCommand (.NET Core 3.1)
gantt
    title Execution time (ms) FakeDbCommand (.NET Core 3.1)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (7874) - mean (117ms)  : 111, 123
    master - mean (117ms)  : 111, 122

    section Bailout
    This PR (7874) - mean (118ms)  : 111, 125
    master - mean (117ms)  : 110, 125

    section CallTarget+Inlining+NGEN
    This PR (7874) - mean (755ms)  : 707, 802
    master - mean (758ms)  : 718, 798

Loading
FakeDbCommand (.NET 6)
gantt
    title Execution time (ms) FakeDbCommand (.NET 6)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (7874) - mean (105ms)  : 99, 111
    master - mean (105ms)  : 100, 110

    section Bailout
    This PR (7874) - mean (107ms)  : 99, 115
    master - mean (107ms)  : 102, 112

    section CallTarget+Inlining+NGEN
    This PR (7874) - mean (708ms)  : 682, 735
    master - mean (703ms)  : 672, 734

Loading
FakeDbCommand (.NET 8)
gantt
    title Execution time (ms) FakeDbCommand (.NET 8)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (7874) - mean (104ms)  : 97, 111
    master - mean (103ms)  : 95, 110

    section Bailout
    This PR (7874) - mean (105ms)  : 97, 112
    master - mean (107ms)  : 99, 115

    section CallTarget+Inlining+NGEN
    This PR (7874) - mean (686ms)  : 645, 727
    master - mean (684ms)  : 642, 725

Loading
HttpMessageHandler (.NET Framework 4.8)
gantt
    title Execution time (ms) HttpMessageHandler (.NET Framework 4.8)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (7874) - mean (193ms)  : 189, 197
    master - mean (193ms)  : 189, 197

    section Bailout
    This PR (7874) - mean (197ms)  : 194, 199
    master - mean (197ms)  : 194, 199

    section CallTarget+Inlining+NGEN
    This PR (7874) - mean (1,116ms)  : 1063, 1169
    master - mean (1,116ms)  : 1062, 1170

Loading
HttpMessageHandler (.NET Core 3.1)
gantt
    title Execution time (ms) HttpMessageHandler (.NET Core 3.1)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (7874) - mean (277ms)  : 272, 282
    master - mean (277ms)  : 271, 283

    section Bailout
    This PR (7874) - mean (277ms)  : 272, 283
    master - mean (277ms)  : 274, 281

    section CallTarget+Inlining+NGEN
    This PR (7874) - mean (902ms)  : 856, 949
    master - mean (911ms)  : 865, 957

Loading
HttpMessageHandler (.NET 6)
gantt
    title Execution time (ms) HttpMessageHandler (.NET 6)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (7874) - mean (269ms)  : 265, 274
    master - mean (271ms)  : 267, 275

    section Bailout
    This PR (7874) - mean (269ms)  : 266, 273
    master - mean (270ms)  : 267, 274

    section CallTarget+Inlining+NGEN
    This PR (7874) - mean (884ms)  : 841, 927
    master - mean (885ms)  : 845, 925

Loading
HttpMessageHandler (.NET 8)
gantt
    title Execution time (ms) HttpMessageHandler (.NET 8)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (7874) - mean (269ms)  : 263, 274
    master - mean (269ms)  : 265, 272

    section Bailout
    This PR (7874) - mean (269ms)  : 265, 272
    master - mean (270ms)  : 267, 273

    section CallTarget+Inlining+NGEN
    This PR (7874) - mean (827ms)  : 810, 845
    master - mean (827ms)  : 806, 848

Loading

Copy link
Member

@lucaspimentel lucaspimentel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM aside from the minor naming issues I commented on.

  • RootSpan should be fixed (FirstSpan?)
  • ToArray()... meh

Aside from reducing allocations, the resulting code looks much cleaner. Thanks!

@andrewlock andrewlock force-pushed the andrew/span-collection branch from 5ae4054 to c02cbdb Compare December 2, 2025 11:02
Copy link
Contributor

@anna-git anna-git left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

@andrewlock andrewlock merged commit 14f72c1 into master Dec 3, 2025
151 checks passed
@andrewlock andrewlock deleted the andrew/span-collection branch December 3, 2025 17:37
@github-actions github-actions bot added this to the vNext-v3 milestone Dec 3, 2025
andrewlock added a commit that referenced this pull request Dec 4, 2025
## Summary of changes

Add additional assembly to public API for unsafe to .NET Standard 2.0

## Reason for change

#7874 reduced the allocation in `TraceContext` and used `unsafe` code.
Apparently this is a new assembly reference for < .NET Core 3.1, and
because we don't run tests on .NET Core 2.1 (ever) or .NET Core 3.0
tests (on PRs), we missed it.

## Implementation details

Added the assembly reference, and confirmed it passes for both .NET Core
2.1 and 3.0 now.

## Test coverage

Covered by existing

## Other details

Raises the question of whether we _should_ be testing one of those on
PRs again, given there's whole code paths that go untouched otherwise 😅
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:tracer The core tracer library (Datadog.Trace, does not include OpenTracing, native code, or integrations) type:performance Performance, speed, latency, resource usage (CPU, memory)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants