Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit f92dc18

Browse files
committed
Fix access to Task.Id while finishing continuations
Task.Id is lazily-initialized with an interlocked operation and we strive to avoid accessing it anywhere in Task's internals on hot paths, but apparently when some ETW logging was added around continuations, calls were added that access Task.Id even if logging is disabled. This is accounting for ~30% of the cycles consumed in a TCS Task's lifecycle! This commit fixes it by making sure these accesses to Id are guarded.
1 parent 4181cfa commit f92dc18

File tree

1 file changed

+14
-3
lines changed
  • src/mscorlib/src/System/Threading/Tasks

1 file changed

+14
-3
lines changed

src/mscorlib/src/System/Threading/Tasks/Task.cs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3585,7 +3585,12 @@ internal void FinishContinuations()
35853585
// Atomically store the fact that this task is completing. From this point on, the adding of continuations will
35863586
// result in the continuations being run/launched directly rather than being added to the continuation list.
35873587
object continuationObject = Interlocked.Exchange(ref m_continuationObject, s_taskCompletionSentinel);
3588-
TplEtwProvider.Log.RunningContinuation(Id, continuationObject);
3588+
TplEtwProvider etw = TplEtwProvider.Log;
3589+
bool tplEtwProviderLoggingEnabled = etw.IsEnabled();
3590+
if (tplEtwProviderLoggingEnabled)
3591+
{
3592+
etw.RunningContinuation(Id, continuationObject);
3593+
}
35893594

35903595
// If continuationObject == null, then we don't have any continuations to process
35913596
if (continuationObject != null)
@@ -3658,7 +3663,10 @@ internal void FinishContinuations()
36583663
var tc = continuations[i] as StandardTaskContinuation;
36593664
if (tc != null && (tc.m_options & TaskContinuationOptions.ExecuteSynchronously) == 0)
36603665
{
3661-
TplEtwProvider.Log.RunningContinuationList(Id, i, tc);
3666+
if (tplEtwProviderLoggingEnabled)
3667+
{
3668+
etw.RunningContinuationList(Id, i, tc);
3669+
}
36623670
continuations[i] = null; // so that we can skip this later
36633671
tc.Run(this, bCanInlineContinuations);
36643672
}
@@ -3672,7 +3680,10 @@ internal void FinishContinuations()
36723680
object currentContinuation = continuations[i];
36733681
if (currentContinuation == null) continue;
36743682
continuations[i] = null; // to enable free'ing up memory earlier
3675-
TplEtwProvider.Log.RunningContinuationList(Id, i, currentContinuation);
3683+
if (tplEtwProviderLoggingEnabled)
3684+
{
3685+
etw.RunningContinuationList(Id, i, currentContinuation);
3686+
}
36763687

36773688
// If the continuation is an Action delegate, it came from an await continuation,
36783689
// and we should use AwaitTaskContinuation to run it.

0 commit comments

Comments
 (0)