KEMBAR78
Reduce allocation in Activity.{Parent}Id by stephentoub · Pull Request #86685 · dotnet/runtime · GitHub
Skip to content

Conversation

@stephentoub
Copy link
Member

When activities are enabled, we end up allocating Activity.Id eg once per HTTP request, and in addition to the result string, Id is allocating both a two-char string from a span as well as a string[6], both of which can be avoided.

Method Toolchain Mean Ratio Allocated Alloc Ratio
Test \main\corerun.exe 7.814 ms 1.00 22.89 MB 1.00
Test \pr\corerun.exe 4.240 ms 0.54 12.97 MB 0.57
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using System;
using System.Diagnostics;
using System.Linq.Expressions;
using System.Reflection;

[MemoryDiagnoser(false)]
[HideColumns("Error", "StdDev", "Median")]
public class Program
{
    public static void Main(string[] args) => BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);

    private Action<Activity, string> _setter;

    [GlobalSetup]
    public void Setup()
    {
        Activity.DefaultIdFormat = ActivityIdFormat.W3C;
        _setter = BuildSetter<Activity, string>(typeof(Activity).GetField("_id", BindingFlags.NonPublic | BindingFlags.Instance));
    }

    [Benchmark]
    public void Test()
    {
        using Activity activity = new Activity("Test");
        activity.Start();
        Action<Activity, string> setter = _setter;
        for (int i = 0; i < 100_000; i++)
        {
            _ = activity.Id;
            setter(activity, null);
        }
        activity.Stop();
    }

    private static Action<TSource, TArg> BuildSetter<TSource, TArg>(FieldInfo field)
    {
        ParameterExpression target = Expression.Parameter(typeof(TSource));
        ParameterExpression value = Expression.Parameter(typeof(TArg));
        return Expression.Lambda<Action<TSource, TArg>>(
            Expression.Assign(Expression.Field(target, field), value),
            target,
            value).Compile();
    }
}

@ghost
Copy link

ghost commented May 24, 2023

Tagging subscribers to this area: @tarekgh, @tommcdon, @pjanotti
See info in area-owners.md if you want to be subscribed.

Issue Details

When activities are enabled, we end up allocating Activity.Id eg once per HTTP request, and in addition to the result string, Id is allocating both a two-char string from a span as well as a string[6], both of which can be avoided.

Method Toolchain Mean Ratio Allocated Alloc Ratio
Test \main\corerun.exe 7.814 ms 1.00 22.89 MB 1.00
Test \pr\corerun.exe 4.240 ms 0.54 12.97 MB 0.57
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using System;
using System.Diagnostics;
using System.Linq.Expressions;
using System.Reflection;

[MemoryDiagnoser(false)]
[HideColumns("Error", "StdDev", "Median")]
public class Program
{
    public static void Main(string[] args) => BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);

    private Action<Activity, string> _setter;

    [GlobalSetup]
    public void Setup()
    {
        Activity.DefaultIdFormat = ActivityIdFormat.W3C;
        _setter = BuildSetter<Activity, string>(typeof(Activity).GetField("_id", BindingFlags.NonPublic | BindingFlags.Instance));
    }

    [Benchmark]
    public void Test()
    {
        using Activity activity = new Activity("Test");
        activity.Start();
        Action<Activity, string> setter = _setter;
        for (int i = 0; i < 100_000; i++)
        {
            _ = activity.Id;
            setter(activity, null);
        }
        activity.Stop();
    }

    private static Action<TSource, TArg> BuildSetter<TSource, TArg>(FieldInfo field)
    {
        ParameterExpression target = Expression.Parameter(typeof(TSource));
        ParameterExpression value = Expression.Parameter(typeof(TArg));
        return Expression.Lambda<Action<TSource, TArg>>(
            Expression.Assign(Expression.Field(target, field), value),
            target,
            value).Compile();
    }
}
Author: stephentoub
Assignees: stephentoub
Labels:

area-System.Diagnostics.Tracing

Milestone: -

@stephentoub stephentoub requested a review from tarekgh May 24, 2023 04:56
@stephentoub stephentoub merged commit dafc07d into dotnet:main May 24, 2023
@stephentoub stephentoub deleted the activityid branch May 24, 2023 16:37
@ghost ghost locked as resolved and limited conversation to collaborators Jun 23, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants