microsoft / microsoft/perfview

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

Open
#2,130 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C#
Stars
4.7k
Forks
775
Avg merge
5d 11h
Merged PRs (30d)
9

Description

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:

  • Does not belong to an activity when using yield: Yield.zip
  • Does belong to an activity when using delay: Delay.zip

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\

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Compare the attached Yield.zip and Delay.zip traces, focusing on the CallTree attribution for GetForecasts() after Task.Yield() versus Task.Delay(5). Reproduce the GET /weatherforecast examples on ASP.NET Core 8.0, including both minimal and controller-based APIs, then determine whether the differing activity attribution is expected and identify the relevant PerfView behavior to document or correct.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
observability, performance, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.