Skip to content

Commit 0ffb238

Browse files
authored
Rework AsyncHelpers await helpers for correctness and efficiency (#128528)
There was a subtle behavior difference between runtime async and async1 continuations when multiple of them were registered on a task. For async1, `Task.RunContinuations` will run async1 continuations except the first one in parallel, and then synchronously invoke the first one. However, for runtime async we were using `ITaskCompletionAction` in this case. This has different behavior: when multiple of these are present they are all invoked sequentially. See the test introduced in this PR (which was based on [this](https://github.com/dotnet/runtime/blob/4e4d02afbe0b8144c8b3c8f1fdf25cacf5663b3c/src/libraries/System.Runtime/tests/System.Threading.Tasks.Tests/System.Runtime.CompilerServices/TaskAwaiterTests.cs#L182-L186) test). This PR fixes the problem by making `TaskContinuation` the continuation object registered on `Task` instances, instead of `RuntimeAsyncTask`. To that end rename the class to `RuntimeAsyncTaskContinuation` and teach `Task.RunContinuations` about this kind of continuation. It differs from `ITaskCompletionAction` in that all such instances are run in parallel, with only the first instance being invoked synchronously. Then consistently use this object as the continuation object for task awaits. This is done for both `AsyncHelpers.TransparentAwait` and `AsyncHelpers.Await`, so all `Await` calls are changed to use similar task-caching optimization as we were doing for value task awaits before. In addition optimize them in several ways: - Teach the JIT to allow inlining of async functions when all awaits are tail awaits (using `AsyncHelpers.TailAwait`) - Rewrite all await helpers in the tail await shape to allow inlining of them - Optimize all await paths to use hand rolled continuations with caching and that avoids additional async1 continuation allocations
1 parent ac7b8a0 commit 0ffb238

18 files changed

Lines changed: 725 additions & 221 deletions

File tree

src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -206,9 +206,9 @@
206206
<Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\GenericsHelpers.cs" />
207207
<Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\InitHelpers.cs" />
208208
<Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\AsyncHelpers.CoreCLR.cs" />
209-
<Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\AsyncHelpers.TaskContinuation.cs" />
210-
<Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\AsyncHelpers.ValueTaskContinuation.cs" />
209+
<Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\AsyncHelpers.ValueTaskSourceContinuation.cs" />
211210
<Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\AsyncProfiler.CoreCLR.cs" />
211+
<Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\RuntimeAsyncTaskContinuation.cs" />
212212
<Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\RuntimeHelpers.CoreCLR.cs" />
213213
<Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\StaticsHelpers.cs" />
214214
<Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\VirtualDispatchHelpers.cs" />
@@ -292,7 +292,7 @@
292292
<ItemGroup Condition="'$(FeatureCominterop)' != 'true'">
293293
<Compile Include="$(BclSourcesRoot)\Internal\Runtime\InteropServices\ComActivator.PlatformNotSupported.cs" />
294294
</ItemGroup>
295-
<ItemGroup Condition="'$(TargetsUnix)' == 'true' or '$(TargetsBrowser)' == 'true'" >
295+
<ItemGroup Condition="'$(TargetsUnix)' == 'true' or '$(TargetsBrowser)' == 'true'">
296296
<Compile Include="$(BclSourcesRoot)\Internal\Runtime\InteropServices\InMemoryAssemblyLoader.PlatformNotSupported.cs" />
297297
<Compile Include="$(BclSourcesRoot)\Interop\Unix\Interop.Libraries.cs" />
298298
</ItemGroup>
@@ -311,7 +311,7 @@
311311

312312
<!-- Enable unsupported browser warnings -->
313313
<ItemGroup Condition="'$(TargetsBrowser)' == 'true' or '$(TargetsAnyOS)' == 'true'">
314-
<SupportedPlatform Include="browser"/>
314+
<SupportedPlatform Include="browser" />
315315
</ItemGroup>
316316

317317
<!-- Include additional sources shared files in the compilation -->

0 commit comments

Comments
 (0)