Skip to content

[WIP] Performance improvements#7071

Draft
martincostello wants to merge 1 commit intoopen-telemetry:mainfrom
martincostello:performance-tweaks
Draft

[WIP] Performance improvements#7071
martincostello wants to merge 1 commit intoopen-telemetry:mainfrom
martincostello:performance-tweaks

Conversation

@martincostello
Copy link
Copy Markdown
Member

Changes

Apply some performance improvements suggested by Copilot after prompting it to look for quick wins.

For now these are just for review to see what people think - some of the improvements seem like gains, but some of the others might be trying to get gains at the expense of functional correctness.

For any changes that seem correct and worth taking, I can split them out into separate PRs as the files touch 3 different projects.

For any changes that didn't seem to be covered by existing benchmarks, new benchmarks have been added.

Benchmark results

Copilot Summary

Suite Rows Duration Δ Duration ratio Allocation Δ Allocation ratio
Benchmarks.Context.BaggageBenchmarks 15 -89.42% 0.11x -55.51% 0.45x
Benchmarks.Context.Propagation.BaggagePropagatorBenchmarks 12 -1.41% 0.99x 0.00% 1.00x
Benchmarks.Context.Propagation.TraceContextPropagatorBenchmarks 6 -1.29% 0.99x 0.00% 1.00x
Benchmarks.Exporter.OtlpMetricExporterBenchmarks 2 -2.75% 0.97x 0.00% 1.00x
Benchmarks.Metrics.HistogramAdviceBenchmarks 6 -1.14% 0.99x -0.02% 1.00x
Expand to see

main + the new benchmarks

BaggageBenchmarks

BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.8117/25H2/2025Update/HudsonValley2)
13th Gen Intel Core i7-13700H 2.90GHz, 1 CPU, 20 logical and 14 physical cores
.NET SDK 10.0.201
  [Host]     : .NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v3
  DefaultJob : .NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v3
Method ItemCount Mean Error StdDev Median Gen0 Allocated
SetBaggageNoOp 1 26.00 ns 0.493 ns 0.437 ns 26.13 ns 0.0198 248 B
SetBaggageSingleUpdate 1 25.01 ns 0.205 ns 0.192 ns 25.00 ns 0.0198 248 B
RemoveMissingBaggage 1 18.76 ns 0.226 ns 0.212 ns 18.70 ns 0.0172 216 B
EqualsSameBackingStore 1 56.00 ns 0.420 ns 0.393 ns 55.94 ns 0.0172 216 B
EqualsEquivalentContents 1 103.85 ns 0.884 ns 0.827 ns 104.05 ns 0.0172 216 B
SetBaggageNoOp 5 95.44 ns 13.875 ns 40.909 ns 64.92 ns 0.0286 360 B
SetBaggageSingleUpdate 5 65.78 ns 0.784 ns 0.733 ns 65.86 ns 0.0286 360 B
RemoveMissingBaggage 5 39.66 ns 0.355 ns 0.332 ns 39.68 ns 0.0261 328 B
EqualsSameBackingStore 5 249.46 ns 1.939 ns 1.813 ns 249.89 ns 0.0501 632 B
EqualsEquivalentContents 5 254.07 ns 2.531 ns 2.368 ns 253.79 ns 0.0501 632 B
SetBaggageNoOp 20 227.84 ns 2.010 ns 1.782 ns 228.30 ns 0.0644 808 B
SetBaggageSingleUpdate 20 229.16 ns 1.471 ns 1.304 ns 229.21 ns 0.0644 808 B
RemoveMissingBaggage 20 113.47 ns 0.847 ns 0.792 ns 113.57 ns 0.0618 776 B
EqualsSameBackingStore 20 922.83 ns 4.654 ns 4.354 ns 923.58 ns 0.1745 2192 B
EqualsEquivalentContents 20 903.11 ns 13.282 ns 11.774 ns 902.23 ns 0.1745 2192 B

BaggagePropagatorBenchmarks

BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.8117/25H2/2025Update/HudsonValley2)
13th Gen Intel Core i7-13700H 2.90GHz, 1 CPU, 20 logical and 14 physical cores
.NET SDK 10.0.201
  [Host]     : .NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v3
  DefaultJob : .NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v3
Method ItemCount UseSpecialChars Mean Error StdDev Gen0 Gen1 Allocated
Extract 1 False 49.09 ns 0.642 ns 0.569 ns 0.0274 - 344 B
Inject 1 False 33.45 ns 0.684 ns 0.814 ns 0.0121 - 152 B
Extract 1 True 144.50 ns 2.626 ns 2.456 ns 0.0618 - 776 B
Inject 1 True 99.29 ns 1.494 ns 1.397 ns 0.0343 - 432 B
Extract 5 False 179.26 ns 3.126 ns 2.924 ns 0.0701 0.0002 880 B
Inject 5 False 122.88 ns 0.479 ns 0.400 ns 0.0389 - 488 B
Extract 5 True 689.59 ns 12.110 ns 10.113 ns 0.2422 0.0010 3040 B
Inject 5 True 391.63 ns 7.153 ns 6.341 ns 0.1535 - 1928 B
Extract 20 False 648.01 ns 5.723 ns 4.779 ns 0.2842 0.0048 3576 B
Inject 20 False 400.14 ns 6.546 ns 5.803 ns 0.1593 0.0005 2000 B
Extract 20 True 2,726.30 ns 25.085 ns 23.464 ns 0.9766 0.0229 12296 B
Inject 20 True 1,512.12 ns 13.904 ns 11.610 ns 0.5436 0.0038 6832 B

TraceContextPropagatorBenchmarks

BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.8117/25H2/2025Update/HudsonValley2)
13th Gen Intel Core i7-13700H 2.90GHz, 1 CPU, 20 logical and 14 physical cores
.NET SDK 10.0.201
  [Host]     : .NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v3
  DefaultJob : .NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v3
Method LongListMember MembersCount Mean Error StdDev Ratio RatioSD Gen0 Gen1 Allocated Alloc Ratio
Extract False 0 81.50 ns 1.153 ns 1.079 ns 1.00 0.02 0.0312 - 392 B 1.00
Extract False 4 369.72 ns 6.632 ns 6.204 ns 1.00 0.02 0.1783 0.0010 2240 B 1.00
Extract False 32 2,020.38 ns 29.656 ns 27.740 ns 1.00 0.02 0.9804 - 12312 B 1.00
Extract True 0 86.94 ns 0.513 ns 0.428 ns 1.00 0.01 0.0312 - 392 B 1.00
Extract True 4 2,103.91 ns 40.700 ns 57.056 ns 1.00 0.04 1.2283 0.0496 15456 B 1.00
Extract True 32 14,382.64 ns 119.399 ns 105.844 ns 1.00 0.01 8.0261 1.6022 100792 B 1.00

OtlpMetricExporterBenchmarks

BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.8117/25H2/2025Update/HudsonValley2)
13th Gen Intel Core i7-13700H 2.90GHz, 1 CPU, 20 logical and 14 physical cores
.NET SDK 10.0.201
  [Host]     : .NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v3
  DefaultJob : .NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v3
Method Mean Error StdDev Gen0 Gen1 Allocated
ExportCounterWithScalarTags 52.47 μs 0.984 μs 1.093 μs 0.3662 0.2441 5.31 KB
ExportHistogramWithFilteredArrayTags 49.37 μs 0.575 μs 0.510 μs 0.3662 0.2441 5.38 KB

HistogramAdviceBenchmarks

BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.8117/25H2/2025Update/HudsonValley2)
13th Gen Intel Core i7-13700H 2.90GHz, 1 CPU, 20 logical and 14 physical cores
.NET SDK 10.0.201
  [Host]     : .NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v3
  DefaultJob : .NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v3
Method ValueType Mean Error StdDev Gen0 Gen1 Gen2 Allocated
BuildProviderAndCollect Byte 196.4 μs 3.77 μs 5.04 μs 45.4102 45.4102 45.4102 264.54 KB
BuildProviderAndCollect Double 184.9 μs 3.59 μs 4.28 μs 45.4102 45.4102 45.4102 264.57 KB
BuildProviderAndCollect Int16 181.2 μs 3.44 μs 3.22 μs 45.4102 45.4102 45.4102 264.55 KB
BuildProviderAndCollect Int32 176.2 μs 3.49 μs 4.28 μs 45.4102 45.4102 45.4102 264.58 KB
BuildProviderAndCollect Int64 182.8 μs 3.59 μs 5.14 μs 45.4102 45.4102 45.4102 264.59 KB
BuildProviderAndCollect Single 183.5 μs 3.67 μs 7.97 μs 45.4102 45.4102 45.4102 264.67 KB

This PR

BaggageBenchmarks

BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.8117/25H2/2025Update/HudsonValley2)
13th Gen Intel Core i7-13700H 2.90GHz, 1 CPU, 20 logical and 14 physical cores
.NET SDK 10.0.201
  [Host]     : .NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v3
  DefaultJob : .NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v3
Method ItemCount Mean Error StdDev Gen0 Allocated
SetBaggageNoOp 1 7.8334 ns 0.1777 ns 0.1975 ns 0.0025 32 B
SetBaggageSingleUpdate 1 32.2689 ns 0.6238 ns 0.5530 ns 0.0197 248 B
RemoveMissingBaggage 1 2.2039 ns 0.0539 ns 0.0504 ns - -
EqualsSameBackingStore 1 0.1991 ns 0.0033 ns 0.0029 ns - -
EqualsEquivalentContents 1 55.7622 ns 0.7667 ns 0.7171 ns 0.0172 216 B
SetBaggageNoOp 5 26.3823 ns 0.2482 ns 0.2321 ns 0.0025 32 B
SetBaggageSingleUpdate 5 67.2756 ns 0.8569 ns 0.8015 ns 0.0286 360 B
RemoveMissingBaggage 5 2.9260 ns 0.0413 ns 0.0366 ns - -
EqualsSameBackingStore 5 0.1990 ns 0.0030 ns 0.0027 ns - -
EqualsEquivalentContents 5 249.5908 ns 2.7217 ns 2.5459 ns 0.0501 632 B
SetBaggageNoOp 20 96.9302 ns 0.6843 ns 0.6401 ns 0.0025 32 B
SetBaggageSingleUpdate 20 211.5347 ns 1.8282 ns 1.7101 ns 0.0644 808 B
RemoveMissingBaggage 20 2.1998 ns 0.0325 ns 0.0304 ns - -
EqualsSameBackingStore 20 0.2016 ns 0.0071 ns 0.0066 ns - -
EqualsEquivalentContents 20 886.0641 ns 6.8063 ns 6.3666 ns 0.1745 2192 B

BaggagePropagatorBenchmarks

BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.8117/25H2/2025Update/HudsonValley2)
13th Gen Intel Core i7-13700H 2.90GHz, 1 CPU, 20 logical and 14 physical cores
.NET SDK 10.0.201
  [Host]     : .NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v3
  DefaultJob : .NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v3
Method ItemCount UseSpecialChars Mean Error StdDev Gen0 Gen1 Allocated
Extract 1 False 53.04 ns 0.908 ns 0.805 ns 0.0274 - 344 B
Inject 1 False 36.35 ns 0.750 ns 0.802 ns 0.0121 - 152 B
Extract 1 True 146.15 ns 2.875 ns 2.953 ns 0.0618 - 776 B
Inject 1 True 93.16 ns 1.702 ns 3.154 ns 0.0343 - 432 B
Extract 5 False 175.45 ns 1.752 ns 1.639 ns 0.0701 0.0002 880 B
Inject 5 False 113.23 ns 1.095 ns 1.024 ns 0.0389 - 488 B
Extract 5 True 626.48 ns 3.350 ns 2.970 ns 0.2422 0.0010 3040 B
Inject 5 True 392.10 ns 4.194 ns 3.923 ns 0.1535 - 1928 B
Extract 20 False 645.88 ns 3.673 ns 3.436 ns 0.2842 0.0048 3576 B
Inject 20 False 395.95 ns 3.000 ns 2.659 ns 0.1593 0.0005 2000 B
Extract 20 True 2,656.33 ns 52.381 ns 58.221 ns 0.9766 0.0229 12296 B
Inject 20 True 1,451.26 ns 13.755 ns 12.194 ns 0.5436 0.0038 6832 B

TraceContextPropagatorBenchmarks

BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.8117/25H2/2025Update/HudsonValley2)
13th Gen Intel Core i7-13700H 2.90GHz, 1 CPU, 20 logical and 14 physical cores
.NET SDK 10.0.201
  [Host]     : .NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v3
  DefaultJob : .NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v3
Method LongListMember MembersCount Mean Error StdDev Ratio RatioSD Gen0 Gen1 Allocated Alloc Ratio
Extract False 0 88.32 ns 0.537 ns 0.503 ns 1.00 0.01 0.0312 - 392 B 1.00
Extract False 4 360.15 ns 7.172 ns 13.114 ns 1.00 0.05 0.1783 0.0010 2240 B 1.00
Extract False 32 1,932.38 ns 11.855 ns 10.510 ns 1.00 0.01 0.9804 - 12312 B 1.00
Extract True 0 86.34 ns 0.504 ns 0.447 ns 1.00 0.01 0.0312 - 392 B 1.00
Extract True 4 1,987.34 ns 14.029 ns 12.437 ns 1.00 0.01 1.2283 0.0496 15456 B 1.00
Extract True 32 14,048.96 ns 111.334 ns 104.142 ns 1.00 0.01 8.0261 1.6022 100792 B 1.00

OtlpMetricExporterBenchmarks

BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.8117/25H2/2025Update/HudsonValley2)
13th Gen Intel Core i7-13700H 2.90GHz, 1 CPU, 20 logical and 14 physical cores
.NET SDK 10.0.201
  [Host]     : .NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v3
  DefaultJob : .NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v3
Method Mean Error StdDev Gen0 Gen1 Allocated
ExportCounterWithScalarTags 49.88 μs 0.511 μs 0.453 μs 0.3662 0.2441 5.31 KB
ExportHistogramWithFilteredArrayTags 49.12 μs 0.459 μs 0.430 μs 0.3662 0.2441 5.38 KB

HistogramAdviceBenchmarks

BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.8117/25H2/2025Update/HudsonValley2)
13th Gen Intel Core i7-13700H 2.90GHz, 1 CPU, 20 logical and 14 physical cores
.NET SDK 10.0.201
  [Host]     : .NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v3
  DefaultJob : .NET 10.0.5 (10.0.5, 10.0.526.15411), X64 RyuJIT x86-64-v3
Method ValueType Mean Error StdDev Gen0 Gen1 Gen2 Allocated
BuildProviderAndCollect Byte 192.9 μs 1.88 μs 3.49 μs 45.4102 45.4102 45.4102 264.52 KB
BuildProviderAndCollect Double 180.9 μs 3.56 μs 4.51 μs 45.4102 45.4102 45.4102 264.54 KB
BuildProviderAndCollect Int16 179.0 μs 3.34 μs 4.22 μs 45.4102 45.4102 45.4102 264.51 KB
BuildProviderAndCollect Int32 180.6 μs 3.51 μs 5.96 μs 45.4102 45.4102 45.4102 264.51 KB
BuildProviderAndCollect Int64 174.7 μs 3.44 μs 3.68 μs 45.4102 45.4102 45.4102 264.51 KB
BuildProviderAndCollect Single 184.2 μs 3.62 μs 7.87 μs 45.4102 45.4102 45.4102 264.62 KB

Merge requirement checklist

  • CONTRIBUTING guidelines followed (license requirements, nullable enabled, static analysis, etc.)
  • Unit tests added/updated
  • Appropriate CHANGELOG.md files updated for non-trivial changes
  • Changes in public API reviewed (if applicable)

Apply some performance improvements suggested by Copilot after prompting it to look for quick wins.
@github-actions github-actions bot added pkg:OpenTelemetry.Api Issues related to OpenTelemetry.Api NuGet package pkg:OpenTelemetry.Exporter.OpenTelemetryProtocol Issues related to OpenTelemetry.Exporter.OpenTelemetryProtocol NuGet package pkg:OpenTelemetry Issues related to OpenTelemetry NuGet package perf Performance related labels Apr 13, 2026
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 13, 2026

Codecov Report

❌ Patch coverage is 85.96491% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.54%. Comparing base (a2b6372) to head (1fe016b).
⚠️ Report is 37 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/OpenTelemetry/Metrics/MetricStreamIdentity.cs 80.00% 6 Missing ⚠️
...mentation/ExportClient/Grpc/GrpcProtocolHelpers.cs 0.00% 2 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #7071      +/-   ##
==========================================
- Coverage   88.54%   88.54%   -0.01%     
==========================================
  Files         270      270              
  Lines       12884    12935      +51     
==========================================
+ Hits        11408    11453      +45     
- Misses       1476     1482       +6     
Flag Coverage Δ
unittests-Project-Experimental 88.34% <85.96%> (-0.11%) ⬇️
unittests-Project-Stable 88.23% <85.96%> (-0.24%) ⬇️
unittests-Solution 88.51% <85.96%> (-0.01%) ⬇️
unittests-UnstableCoreLibraries-Experimental 40.87% <3.63%> (-0.79%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/OpenTelemetry.Api/Baggage.cs 100.00% <100.00%> (ø)
src/OpenTelemetry/ReadOnlyFilteredTagCollection.cs 100.00% <100.00%> (ø)
...mentation/ExportClient/Grpc/GrpcProtocolHelpers.cs 62.50% <0.00%> (+11.21%) ⬆️
src/OpenTelemetry/Metrics/MetricStreamIdentity.cs 87.36% <80.00%> (-5.14%) ⬇️

... and 5 files with indirect coverage changes

}

throw new InvalidOperationException($"Multiple {name} headers.");
#else
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Should compare the numbers for net462, because the code looks identical, but there's probably a reason it differs other than just where the TryGet() is getting values from.

@martincostello martincostello added the keep-open Prevents issues and pull requests being closed as stale label Apr 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

keep-open Prevents issues and pull requests being closed as stale perf Performance related pkg:OpenTelemetry.Api Issues related to OpenTelemetry.Api NuGet package pkg:OpenTelemetry.Exporter.OpenTelemetryProtocol Issues related to OpenTelemetry.Exporter.OpenTelemetryProtocol NuGet package pkg:OpenTelemetry Issues related to OpenTelemetry NuGet package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant