Shrink AsyncMethodBuilder.MoveNextRunner by a field in common case (dotnet/coreclr...
authorStephen Toub <stoub@microsoft.com>
Fri, 20 May 2016 20:50:38 +0000 (14:50 -0600)
committerJan Kotas <jkotas@microsoft.com>
Fri, 20 May 2016 20:50:38 +0000 (13:50 -0700)
commit079fca16c8a15418c71117f348f3caa2bf22b4ad
tree4e9a3e554c27557ee8b256ffa50bf72987697af9
parent6dccf129cf3e6fce7c8f7a3ca93f31860d85b268
Shrink AsyncMethodBuilder.MoveNextRunner by a field in common case (dotnet/coreclr#5131)

When an async method yields for the first time, there are several allocations, including a "MoveNextRunner" object that used to store the state machine and an ExecutionContext.  However, for the common case where a default ExecutionContext is being used, we can avoid needing that field.  For the simplest async method, this can reduce the total size of the allocations by ~4%.

(It would be nice in this case to be able to get rid of the MoveNextRunner entirely.  However, the Action delegate that gets created needs to be stored into the builder before the builder is boxed to the heap, so that the cached delegate gets boxed with it; otherwise, the second yield in the async method will end up needing to reallocate the delegate.  Since delegates are immutable, if the delegate was to point directly to a method on the boxed object, we would need to first have the object, a catch-22.  So the MoveNextRunner serves as an intermediary that lets us create the delegate, store it into the struct builder, then box the builder, and then store the boxed object into the runner.)

Commit migrated from https://github.com/dotnet/coreclr/commit/ce3ff76234bf199b4498a5d31f05af6eb43073f6
src/coreclr/src/mscorlib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs