异步等待的表现? [英] async await performance?
问题描述
的(只是一个理论性的问题 - 对于非GUI应用)的
假设我有这样的code。与许多等待
:
Assuming I have this code with many awaits
:
public async Task<T> ConsumeAsync()
{
await A();
await b();
await c();
await d();
//..
}
每个任务花费的时间很短的时间,
Where each task can take a very short period of time ,
问(再次,理论)
有可能的情况,其中的总体时间处理的与所有那些释放回线程和读取线程背(红色和放大器;绿色在这里:)
There could be a situation where the overall time dealing with all those "releasing back threads" and "fetching threads back" ( red & green here :)
正在采取的更多的时间比单个线程可能完成所有的工作延迟少量的,
Is taking more time than a single thread which could done all the work with a small amount of delay ,
我的意思是,我想成为最有生产力的,而是因为所有的来回切换 - 我居然瘦了生产效率。
I mean , I wanted to be the most productive , but instead , since all those switches back and forth - I actually lost productivity.
这样的场景可发生?
推荐答案
A 任务
对象重新present的待处理操作的结果延期。您不必使用任务和异步/的await
如果您没有任何挂起的操作。否则,我相信异步
/ 等待
code通常比裸TPL ContinueWith
模拟。
A Task
object represent the deferred result of a pending operation. You don't have to use tasks and async/await
if you don't have any pending operations. Otherwise, I believe async
/await
code is generally more efficient than its bare TPL ContinueWith
analogue.
让我们做一些时机:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication
{
class Program
{
// async/await version
static async Task<int> Test1Async(Task<int> task)
{
return await task;
}
// TPL version
static Task<int> Test2Async(Task<int> task)
{
return task.ContinueWith(
t => t.Result,
CancellationToken.None,
TaskContinuationOptions.ExecuteSynchronously,
TaskScheduler.Default);
}
static void Tester(string name, Func<Task<int>, Task<int>> func)
{
var sw = new System.Diagnostics.Stopwatch();
sw.Start();
for (int i = 0; i < 10000000; i++)
{
func(Task.FromResult(0)).Wait();
}
sw.Stop();
Console.WriteLine("{0}: {1}ms", name, sw.ElapsedMilliseconds);
}
static void Main(string[] args)
{
Tester("Test1Async", Test1Async);
Tester("Test2Async", Test2Async);
}
}
}
输出:
Test1Async: 1582ms
Test2Async: 4975ms
所以,在默认情况下,的await
延续更有效地比 ContinueWith
延续处理。让我们来稍微优化这个code:
So, by default, await
continuations are handled more efficiently than ContinueWith
continuations. Let's optimize this code slightly:
// async/await version
static async Task<int> Test1Async(Task<int> task)
{
if (task.IsCompleted)
return task.Result;
return await task;
}
// TPL version
static Task<int> Test2Async(Task<int> task)
{
if (task.IsCompleted)
return Task.FromResult(task.Result);
return task.ContinueWith(
t => t.Result,
CancellationToken.None,
TaskContinuationOptions.ExecuteSynchronously,
TaskScheduler.Default);
}
输出:
Test1Async: 1557ms
Test2Async: 429ms
现在非异步版本获胜。如果用异步
版,相信这种优化已经由异步/的await
基础设施内部完成。
Now the non-async version wins. In case with the async
version, I believe this optimization has already been done internally by the async/await
infrastructure.
总之,到目前为止,我们只涉及已完成的任务( Task.FromResult
)。让我们来介绍一下实际异步(当然,我们会做迭代次数少这个时候):
Anyway, so far we've dealt only with completed tasks (Task.FromResult
). Let's introduce the actual asynchrony (naturally, we'll do less iterations this time):
static Task<int> DoAsync()
{
var tcs = new TaskCompletionSource<int>();
ThreadPool.QueueUserWorkItem(_ => tcs.SetResult(0));
return tcs.Task;
}
static void Tester(string name, Func<Task<int>, Task<int>> func)
{
ThreadPool.SetMinThreads(200, 200);
var sw = new System.Diagnostics.Stopwatch();
sw.Start();
for (int i = 0; i < 1000000; i++)
{
func(DoAsync()).Wait();
}
sw.Stop();
Console.WriteLine("{0}: {1}ms", name, sw.ElapsedMilliseconds);
}
输出:
Test1Async: 4207ms
Test2Async: 4734ms
现在的差别是非常边缘,虽然异步
版本仍然执行略胜一筹。然而,我认为这样的收益确实是忽略不计,可比的异步操作或恢复为拍摄背景的成本的实际成本时, SynchronizationContext.Current!= NULL
。
Now the difference is very marginal, although the async
version still performs slightly better. Yet I think such gain is really neglectable, comparable to the actual cost of the asynchronous operation or to the cost of restoring the captured context for when SynchronizationContext.Current != null
.
底线是,如果你处理异步任务,去为异步
/ 等待
如果你有一个选择,而不是出于性能原因,但易用性,可读性和可维护性。
The bottom line is, if you deal with asynchronous tasks, go for async
/await
if you have a choice, not for performance reason but for ease of use, readability and maintainability.
这篇关于异步等待的表现?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!