Skip to content

Avoid allocations propagating Activity baggage - #132368

Open
martincostello wants to merge 1 commit into
dotnet:mainfrom
martincostello:avoid-baggage-propagation-allocations
Open

Avoid allocations propagating Activity baggage#132368
martincostello wants to merge 1 commit into
dotnet:mainfrom
martincostello:avoid-baggage-propagation-allocations

Conversation

@martincostello

Copy link
Copy Markdown
Member

Avoid allocations when enumerating baggage in internal code paths by using a struct-based enumerator.

Public API surface is unchanged.

Method Baseline (main) Mean Fixed Mean Ratio Baseline Allocated Fixed Allocated Alloc Ratio
GetBaggageItem 17.10 ns 3.37 ns 5.07x 64 B 0 B 0.00x
EnumerateBaggageViaProperty 30.88 ns 30.24 ns 1.02x 64 B 64 B 1.00x
Benchmarks

Before

BenchmarkDotNet v0.14.0, Windows 11 (10.0.26200.9168)
13th Gen Intel Core i7-13700H, 1 CPU, 20 logical and 14 physical cores
.NET SDK 11.0.100-preview.7.26381.103
  [Host] : .NET 10.0.10 (10.0.1026.32716), X64 RyuJIT AVX2

Toolchain=InProcessEmitToolchain
Method Mean Error StdDev Gen0 Allocated
GetBaggageItem 17.10 ns 0.367 ns 0.477 ns 0.0051 64 B
EnumerateBaggageViaProperty 30.88 ns 0.643 ns 1.343 ns 0.0051 64 B

After

BenchmarkDotNet v0.14.0, Windows 11 (10.0.26200.9168)
13th Gen Intel Core i7-13700H, 1 CPU, 20 logical and 14 physical cores
.NET SDK 11.0.100-preview.7.26381.103
  [Host] : .NET 10.0.10 (10.0.1026.32716), X64 RyuJIT AVX2

Toolchain=InProcessEmitToolchain
Method Mean Error StdDev Gen0 Allocated
GetBaggageItem 3.370 ns 0.1249 ns 0.1227 ns - -
EnumerateBaggageViaProperty 30.241 ns 0.6105 ns 0.6532 ns 0.0051 64 B
using System.Diagnostics;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Running;
using BenchmarkDotNet.Toolchains.InProcess.Emit;

BenchmarkSwitcher.FromAssembly(typeof(Bench).Assembly).Run(args);

public class InProcessConfig : ManualConfig
{
    public InProcessConfig()
    {
        AddJob(Job.Default.WithToolchain(InProcessEmitToolchain.Instance));
        AddDiagnoser(BenchmarkDotNet.Diagnosers.MemoryDiagnoser.Default);
    }
}

[Config(typeof(InProcessConfig))]
public class Bench
{
    private ActivitySource _source = default!;
    private Activity _leaf = default!;

    [GlobalSetup]
    public void Setup()
    {
        _source = new ActivitySource("bench");
        ActivityListener listener = new ActivityListener
        {
            ShouldListenTo = _ => true,
            Sample = (ref ActivityCreationOptions<ActivityContext> _) => ActivitySamplingResult.AllData,
        };
        ActivitySource.AddActivityListener(listener);

        // Build a chain of 5 activities, baggage set on the root only,
        // so GetBaggageItem/Baggage must walk up the parent chain.
        Activity? root = _source.StartActivity("root");
        root!.SetBaggage("key1", "value1");
        root.SetBaggage("key2", "value2");
        root.SetBaggage("key3", "value3");

        Activity current = root;
        for (int i = 0; i < 4; i++)
        {
            current = _source.StartActivity("child" + i)!;
        }

        _leaf = current;
    }

    [Benchmark]
    public string? GetBaggageItem()
    {
        return _leaf.GetBaggageItem("key3");
    }

    [Benchmark]
    public int EnumerateBaggageViaProperty()
    {
        int count = 0;
        foreach (KeyValuePair<string, string?> kvp in _leaf.Baggage)
        {
            count++;
        }
        return count;
    }
}

Avoid allocations when enumerating baggage in internal code paths by using a struct-based enumerator.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI lite review requested due to automatic review settings August 16, 2026 10:05
@dotnet-policy-service dotnet-policy-service Bot added the community-contribution Indicates that the PR has been added by a community member label Aug 16, 2026
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @steveisok, @dotnet/area-system-diagnostics-tracing
See info in area-owners.md if you want to be subscribed.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR reduces allocations in internal baggage-propagation code paths by introducing a struct-based baggage enumerator on Activity and updating propagators to consume it instead of allocating iterator-based enumeration.

Changes:

  • Add an internal Activity.EnumerateBaggage() struct enumerator to traverse baggage across an activity’s ancestor chain without iterator allocations.
  • Update W3C and legacy/ passthrough propagators to pass the Activity and enumerate baggage via the new struct enumerator.
  • Update Activity.GetBaggageItem to use the new enumeration path.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/W3CPropagator.cs Switch baggage injection to use Activity.EnumerateBaggage() (struct enumerator) to avoid iterator allocations.
src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/PassThroughPropagator.cs Thread root Activity through to baggage injection so it can enumerate baggage allocation-free.
src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/LegacyPropagator.cs Switch baggage injection to pass Activity and enumerate via the struct enumerator.
src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DistributedContextPropagator.cs Update internal baggage injection helper to accept Activity? and use struct-based enumeration.
src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs Introduce EnumerateBaggage() and BaggageEnumerator; update GetBaggageItem to use it.

@martincostello
martincostello marked this pull request as ready for review August 16, 2026 12:35
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-System.Diagnostics.Tracing community-contribution Indicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants