Async Profiler: Combine instrumentation flags usage over profiler/tpl/debugger.#130083
Open
lateralusX wants to merge 2 commits into
Open
Conversation
Contributor
|
Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag |
Contributor
|
Tagging subscribers to this area: @dotnet/area-system-threading-tasks |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR refactors async instrumentation gating across CoreLib to consistently use AsyncInstrumentation’s active flag snapshot (covering async profiler, TPL EventSource, and debugger) instead of directly checking TplEventSource.Log.IsEnabled() / Task.s_asyncDebuggingEnabled / older checkpoint helpers.
Changes:
- Introduces a
Tplclient flag and new flag-loading APIs inAsyncInstrumentation, plus plumbing fromTplEventSource.OnEventCommandto keep TPL state synchronized. - Updates multiple awaiter / continuation hot paths to load instrumentation flags once and branch based on
AsyncProfilervsTplvsAsyncDebugger. - Updates async-profiler dispatcher creation/completion APIs to take an explicit
flagssnapshot and adds platform support guards.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TplEventSource.cs | Pushes TPL enable/disable state into AsyncInstrumentation via UpdateTplFlags. |
| src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TaskContinuation.cs | Uses AsyncInstrumentation flags to decide async-profiler dispatcher wrapping and TPL tracing scheduling path. |
| src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs | Documents debugger/Synchronize bit coordination contract for async debugging enablement. |
| src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/YieldAwaitable.cs | Switches await continuation scheduling decisions to consult loaded instrumentation flags. |
| src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ValueTaskAwaiter.cs | Switches async-profiler dispatcher wrapping decisions to consult loaded instrumentation flags. |
| src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/TaskAwaiter.cs | Routes TaskWait* tracing and async-profiler dispatcher wrapping through loaded instrumentation flags. |
| src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/PoolingAsyncValueTaskMethodBuilderT.cs | Updates async-profiler resume/complete/unwind checkpoints to load flags and pass snapshots; adjusts diagnostic-data gating to IsSupported. |
| src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs | Switches async-profiler dispatcher wrapping decisions to consult loaded instrumentation flags. |
| src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncTaskMethodBuilderT.cs | Switches async-profiler resume/complete/unwind checkpoints and TPL tracing to consult loaded instrumentation flags; adjusts diagnostic-data gating to IsSupported. |
| src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncStateMachineDispatcher.cs | Renames/reshapes support checkpoints, threads flags snapshots through dispatcher creation/resume/complete/unwind, and consolidates flag loading. |
| src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncInstrumentation.cs | Adds Tpl client support, splits “supported” checks, introduces LoadFlags APIs, and adds UpdateTplFlags + synchronization logic. |
| src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs | Updates runtime-async instrumentation checkpoints to load and pass the active flag snapshot. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Reworks AsyncInstrumentation so all three instrumentation clients — the async profiler, the async debugger, and the TPL event source — flow through a single unified flags gate, and so that the per-client support checks constant-fold when a feature area is compiled out. This lets the ILLinker dead-code-eliminate the instrumentation paths it can prove are unreachable.
Motivation
Previously the async instrumentation entry points were gated on a monolithic AsyncInstrumentation.IsSupported (Debugger.IsSupported || EventSource.IsSupported) plus ad-hoc checks (e.g. TPL used TplEventSource.Log.IsEnabled() directly, V2 dispatch used RuntimeAsyncInstrumentationHelpers.InstrumentCheckPoint). Because the support check mixed all clients together, the trimmer couldn't remove a given client's instrumentation even when its underlying feature switch was disabled. Since we already need to load and sync the flags, folding TPL+Debugger checks into the same flag check reduce the instructions executed on hot path. The DCE guards also make sure we can eliminate the complete instrumentation block or just individual instrumentation calls depending on what features have been enabled.
It has also been verified that the DCE guards correctly get const folded in Tier1. AsyncInstrumentation.IsActive ends up in one load of s_activeFlags, a compare against 0 and a highly predictable branch bypassing the whole instrumentation block when disabled. The different AsyncInstrumentation.IsEnabled.AsyncProfiler|AsyncDebugger|Tpl all ends up as a simple bit check on the already loaded flags and a highly predicatalbe branch bypassing the respective instrumentation code when disabled.
What changed
Trimming result
Verified with ILLink: with both EventSource and Debugger disabled, virtually all async profiler code is removed. The only residue is the async instrumentation flags themselves and System.Runtime.CompilerServices.AsyncProfiler.Info.
Notes