microsoft / perfview

PerfView is a CPU and memory performance-analysis tool
http://channel9.msdn.com/Series/PerfView-Tutorial
MIT License
4.2k stars 712 forks source link

Why do the frames not belong to its activity when `Task.Yield()` is involved? #2130

Open xiaomi7732 opened 1 week ago

xiaomi7732 commented 1 week ago

In an ASP.NET Core Web application, on the request of GET /weatherforecast, GetForecasts() will be called. However, in the trace, the GetForecasts() does not belong to the activity when putting behind Task.Yield() like this:

app.MapGet("/weatherforecast", async () =>
{
    await Task.Yield();
    return WeatherForecastHelper.GetForecasts();
})

In the CallTree view, the frame is attribute to a IO ThreadPool Worker, but not any activity:

Image

In comparison, only change a line of code, the result is more favorable:

{
    await Task.Delay(5); // Change from Task.Yield()
    return WeatherForecastHelper.GetForecasts();
})

Image

Is this behavior expected? Can you help understand the difference?

Attaching the trace files:

FWIW, I am trying this on ASP.NET Core 8.0 runtime, Windows, and it reproduced for both minimal API and controller based API. Here are some details of the environment:

.NET SDK:
 Version:           8.0.404
 Commit:            7b190310f2
 Workload version:  8.0.400-manifests.c6df56b6
 MSBuild version:   17.11.9+a69bbaaf5

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.22631
 OS Platform: Windows
 RID:         win-x64
 Base Path:   C:\Program Files\dotnet\sdk\8.0.404\