-
Notifications
You must be signed in to change notification settings - Fork 2.1k
[Perf] Don't invoke async state machine unnecessarily #3057
Comments
cc @davidfowl |
Curious: do you have actual numbers showing the performance improvement? DNX has no default synchronization context (well, it has no synchronization context at all 😄), which means that task continuations will always be started on the current task scheduler (the default one if you don't override it) when using I'm pretty sure there's no real gain when using |
The ConfiguredAwait follows this path: SetContinuationForAwait(Action, false, false, StackCrawlMark)
-> AwaitTaskContinuation.UnsafeScheduleAction
-> new AwaitTaskContinuation(Action, false)
-> ThreadPool.UnsafeQueueCustomWorkItem
-> Action() The non-configured await (default scheduler/no synchronization context) follows this path: SetContinuationForAwait(Action, true, true, StackCrawlMark)
-> new AwaitTaskContinuation (Action, true, StackCrawlMark)
-> ExecutionContext.Capture
-> ... bunch of stuff ...
-> AwaitTaskContinuation.Run( , false)
-> ThreadPool.UnsafeQueueCustomWorkItem
-> ExecutionContext.Run(ExecutionContext, GetInvokeActionCallback(), Action, true)
-> ... bunch of stuff ...
-> Action() So the execution path of the non-configured await is more complicated; but perhaps more importantly is that asp.net is a library and its performance should be independent of the caller. If the calling code changes its scheduler or synchronisation context; without ConfigureAwait, the performance of asp.net could drop though the floor as the fast paths are no longer applicable. Quoting @stephentoub : http://blogs.msdn.com/b/pfxteam/archive/2012/06/15/executioncontext-vs-synchronizationcontext.aspx
|
|
Its this line that is the Configured Await: http://referencesource.microsoft.com/#mscorlib/system/runtime/compilerservices/TaskAwaiter.cs,431
|
But the value is hardcoded, |
Its set by the parameter given (e.g. false) http://referencesource.microsoft.com/#mscorlib/system/runtime/compilerservices/TaskAwaiter.cs,401
So:
|
Whereas what you are highlighting is that without ConfigureAwait:
As the flows are done at each await point, if the calling code doesn't do ConfigureAwait it can happily have them flowed regardless of what its awaiting does. |
No, using
http://blogs.msdn.com/b/pfxteam/archive/2012/02/29/10274035.aspx |
Hmm... might need to look into it a bit more :) However, regardless, its still taking a dependency on the calling code not changing the synchronization context |
True. But the real question is: is worth adding tons of super-ugly FYI, even the EF team decided to get rid of |
Hmm, ok I think you've brought me round, might just leave the "return Task rather than awaiting" bits in |
😄 I'm not saying that the changes you suggest are bad, but if you wanna use |
I'll mark it down to an experience hang over from: http://referencesource.microsoft.com/#System.Web/AspNetSynchronizationContext.cs,9b31a5e94e4b9894 Which no longer exists in asp.net 5 ... :) |
Should be better changes |
ConfigureAwait in Async methods; unless only one await and last statement when return Task rather than awaiting.Return task rather than awaiting when no extra work needs to be done after await
The text was updated successfully, but these errors were encountered: