dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.57k stars 4.55k forks source link

[API Proposal]: ThreadLocal<T>.GetEnumerator() #103684

Open benaadams opened 2 weeks ago

benaadams commented 2 weeks ago

Background and motivation

ThreadLocal<T> is a good approach to gather uncontended metrics; however then collating those metrics via ThreadLocal.Values is very allocatey.

It would be better to provide a struct enumerator that can be iterated over for no allocations.

API Proposal

namespace System.Threading;

public class ThreadLocal<T> : IEnumerable<T>
{
    public StructEnumerator GetEnumerator();
    // etc.
}

API Usage

[CounterMetric]
public static long Calls
{
    get
    {
        long total = 0;
        foreach (var value in _calls)
        {
            total += value;
        }
        return total;
    }
}
private static ThreadLocal<long> _calls = new(trackAllValues: true);
public static void IncrementCalls(int delta) => _calls.Value+= delta;

Alternative Designs

No response

Risks

No response

dotnet-policy-service[bot] commented 2 weeks ago

Tagging subscribers to this area: @mangod9 See info in area-owners.md if you want to be subscribed.

MichalPetryka commented 2 weeks ago

Should the enumerator return values or references to the underlying storage? I assume the latter would be problematic due to making mutations from multiple threads possible?

benaadams commented 2 weeks ago

Should the enumerator return values or references to the underlying storage? I assume the latter would be problematic due to making mutations from multiple threads possible?

Values; can always wrap with an object if want reference of values