如何衡量等待异步操作的性能?

我有一个从多个MessageQueue实例读取的Windows服务。 这些消息队列都运行自己的Task来读取消息。 通常,在阅读消息后,I / O数据库的工作就完成了。 我发现文章声称在I / O操作上使用异步是个好主意,因为它可以释放线程。 我正在尝试模拟在控制台应用程序中使用异步I / O操作的性能提升。

控制台应用程序

在我的测试环境中,我有10个队列。 GetQueues()返回10个不同的MessageQueue实例。

 static void Main(string[] args) { var isAsync = Console.ReadLine() == "Y"; foreach (var queue in queueManager.GetQueues()) { var temp = queue; Task.Run(() => ReceiveMessagesForQueue(temp, isAsync)); } while (true) { FillAllQueuesWithMessages(); ResetAndStartStopWatch(); while(!AllMessagesRead()) { Thread.Sleep(10); } Console.WriteLine("All messages read in {0}ms", stopWatch.ElapsedMilliseconds); } } static async Task ReceiveMessagesForQueue(MessageQueue queue, bool isAsync) { while (true) { var message = await Task.Factory.FromAsync(queue.BeginReceive(), queue.EndReceive); if (isAsync) await ProcessMessageAsync(message); else ProcessMessage(message); } } 

异步消息处理

Task.Delay()上使用await,因此应该释放当前的Thread

 static async Task ProcessMessageAsync(Message message) { await Task.Delay(1000); BurnCpu(); } 

同步消息处理

等待Task.Delay() ,所以不应该释放当前的Thread

 static void ProcessMessage(Message message) { Task.Delay(1000).Wait(); BurnCpu(); } 

最后,结果是平等的。 我在这里错过了什么吗?

编辑1

我正在使用stopWatch.ElapsedMilliseconds测量总时间。 我使用FillAllQueuesWithMessages()使用FillAllQueuesWithMessages()或更多消息填充所有队列。

编辑2

ReceiveMessagesForQueue()现在返回Task而不是void

编辑3(修复)

此测试确实显示了我现在的性能改进。 我不得不让BurnCpu()花更多的时间。 在等待BurnCPU()BurnCPU()可以使用已发布的线程进行处理。

使用async-await不会加快执行单个操作所需的时间,它只是意味着您没有等待什么都不做的线程

在你的情况下, Task.Delay将花费一秒钟,无论如何,但在这里:

 Task.Delay(1000).Wait(); 

一个线程,在这里等待第二个结束:

 await Task.Delay(1000); 

没有 。 您仍在异步等待(因此, await ),但没有使用任何线程,这意味着更好的可伸缩性。

async-await您可以获得性能提升,因为您的应用程序可以使用更少的线程执行相同的操作,或者使用相同的线程执行更多操作。 要衡量您需要同时进行大量async操作。 只有这样,您才会注意到async选项比同步选项更好地利用CPU资源。


有关解冻螺纹的更多信息,这里有没有线程

您仍在从线程池中运行其自己的线程中的每个任务 – 因为您正在使用默认任务调度程序。 如果要查看性能损失,则需要确保在同一个线程上执行多个任务。

此外,有20个并行任务,你可能不会看到任何差异。 尝试2,000个任务。