dotnet / runtime

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

Possible regression with [ThreadStatic] in debug builds on .NET 9 RC1 #107728

Closed alexyakunin closed 4 days ago

alexyakunin commented 5 days ago

Description

One of our tests started to run ~20x slower on .NET 9 RC1, if it's compiled in Debug configuration.

That's where it spends most of its time:

image

There is another branch with similar ~38%, and it's also on the same ThreadRandom.get_Instance call.

ThreadRandom looks as follows:

public static class ThreadRandom
{
    [ThreadStatic] private static Random? _instance;

    public static Random Instance {
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        get => _instance ??= CreateInstance();
    }

    private static Random CreateInstance()
        => new(Random.Shared.Next());
}

What's weird is that all of my attempts to reproduce this perf. regression on isolated console app failed, even though a console app running the code of this specific unit test also manifests the regression.

Configuration

Windows 11 machine.

Regression?

Yes, it looks like this is a perf. regression.

Data

No additional data.

Analysis

Not sure what it could be.

dotnet-policy-service[bot] commented 5 days ago

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

mangod9 commented 5 days ago

Thanks for reporting the issue @alexyakunin. Can you please clarify whether you are comparing the perf with .NET 8 or a previous preview version of 9? That would help narrow down the issue.

Adding @davidwrighton since there was some work on ThreadStatics recently.

alexyakunin commented 5 days ago

Yes, I'm comparing the perf. of .NET 9 RC1 vs .NET 8 (8.0.8).

davidwrighton commented 4 days ago

I've confirmed this is a regression in CheckRunClassInitThrowing and several parts of our system could use some checks before doing expensive work. The regression would only likely be visible in a multithreaded application where multiple threads are accessing thread statics, and all of the thread static access was compiled as a DEBUG build, and a few other details..., which is probably why your isolated repro didn't show the slowdown. Our current performance tests do not cover this scenario.

alexyakunin commented 2 days ago

Thanks, guys - that was quick!