13

所以新的异步 CTP 非常酷;它使我的生活变得更轻松,不必编写命名回调方法,并使方法的意图更加清晰。

现在我已经开始使用它了,我想知道 async/await 和“经典”异步回调语法之间可能存在哪些差异。

以下是我想到的一些问题,但还有许多其他问题我现在不会想到,以后可能会想到。

  • 一个是否可能提供优于另一个的性能?
  • 是否存在比另一个更大的开销?
  • 在高性能环境中使用哪个更好?
4

2 回答 2

16

答案很复杂,当前的编译器实现 await 在几个方面都比回调好,但在某些情况下更糟。

.NET 执行上下文:我们打算让 await 和 ContinueWith(...) 捕获和恢复 .NET 执行上下文。否则它不会通过 .NET 安全要求,因为这样您就可以获取任意的东西,如凭据等,并将它们留在线程池中以供下一个工作项使用。对于“等待”,这是我们在内部构建中所做的调整,但这是在我们制作了 //BUILD 开发者预览版之后。

内存分配: 在内存分配方面,'await' 在几个方面比手动回调更好。关键是对于有很多等待的函数,你真正生成的是几个回调的等价物。如果您以线性执行顺序有 5 个等待,并且执行总是流到最后,那么等价的将需要 5 个回调。对于这 5 个回调中的每一个,都可以生成一个单独的 lambda 闭包对象和一个代表该特定 lambda 的委托。在“等待”的情况下,编译器知道您不会将委托对象用于其他任何事情。因此,整个方法共享 1 个闭包和 1 个委托,并使用一个内部状态机来跟踪您在方法内部的位置。因此,对于这种情况,“等待”分配的对象更少,

快捷方式“等待”也具有比回调更高级的语义。在创建回调 lambda 的情况下,编译器无论如何都被迫分配闭包和 lambda 的入口点委托。对于 'await',await 合约允许为已经“完成”的 awaitables 提供更优化的代码路径。如果 awaitable 在评估 await 之前说它已经“完成”,则语义只是拉出结果的纯粹传递。这意味着编译器有机会延迟分配直到您真正需要它,因此您永远不会支付闭包分配、委托分配或调度成本,除非您确实需要它。当前的 Developer Preview 编译器包括这些性能优化。

Trading danger for perf If you really want to bypass the .NET security model, you could kind of imagine a case where you can get a little bit of perf by avoiding the execution context package/restore, if you are absolutely confident that you will never need to capture/restore context. However, most of .NET's methods will do that silently under the covers, so you really need to know which ones will give you raw access without it. The rule of thumb for .NET is that if the API is available in partial trust (e.g. Silverlight), then the API certainly captures context when invoked, and then restores it, if it's an API that tranfers execution elsewhere (e.g. ContinueWith, QueueUserWorkItem(...), etc.). If you roll your own threadpool that just queues up delegates, you can bypass this, but most likely you don't need it.

My personal recommendation Use await. It's higher level, and it's what you want. We've put in a fair amount of effort trying to tune it for this release, and we could probably tune it further. Callback-based APIs will be more limiting, because the compiler can only tune so much before they start breaking the language rules. Awaits in a method allow for you to have smarter closures than callbacks. AND... await is a lot more intuitive to read/use than callbacks :)

于 2011-10-24T11:38:15.667 回答
5

与匿名函数和迭代器一样,asyncandawait关键字是语法糖。从技术意义上讲,它们的效率并不比同等的非含糖版本高或低。它们只是为您节省了大量的打字时间。

于 2011-10-24T03:52:04.487 回答