C# 如何度量等待异步操作的性能?
我有一个Windows服务,可以读取多个C# 如何度量等待异步操作的性能?,c#,task-parallel-library,async-await,performance-testing,c#-5.0,C#,Task Parallel Library,Async Await,Performance Testing,C# 5.0,我有一个Windows服务,可以读取多个MessageQueue实例。这些消息队列都运行自己的任务来读取消息。通常,在读取消息之后,I/O数据库的工作就完成了。我发现一些文章声称在I/O操作中使用异步是个好主意,因为它可以释放线程。我试图模拟在控制台应用程序中使用异步I/O操作的性能提升 控制台应用程序 在我的测试环境中,我有10个队列GetQueues()返回10个不同的MessageQueue实例 static void Main(string[] args) { var isAsy
MessageQueue
实例。这些消息队列都运行自己的任务
来读取消息。通常,在读取消息之后,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<Message>(queue.BeginReceive(), queue.EndReceive);
if (isAsync)
await ProcessMessageAsync(message);
else
ProcessMessage(message);
}
}
同步消息处理
等待Task.Delay()
,因此不应释放当前线程
static async Task ProcessMessageAsync(Message message)
{
await Task.Delay(1000);
BurnCpu();
}
static void ProcessMessage(Message message)
{
Task.Delay(1000).Wait();
BurnCpu();
}
最终,结果是相同的。我是不是遗漏了什么
编辑1
我正在使用秒表测量总时间。ElapsedMilliseconds
。我使用FillAllQueuesWithMessages()
将10、100、10000或更多消息填充到所有队列中
编辑2
ReceiveMessagesForQueue()
现在返回Task
而不是void
编辑3(修复)
这个测试确实显示了我现在的性能改进。我不得不让
BurnCpu()
花更多的时间。当等待Task.Delay()
时,BurnCPU()
可以使用释放的线程进行处理。使用async wait
不会加快执行单个操作所需的时间,这只意味着您没有线程在等待执行任何操作
在您的情况下,任务。延迟
将花费一秒钟,无论发生什么,但在这里:
Task.Delay(1000).Wait();
您有一个线程,在此处等待第二个线程结束:
await Task.Delay(1000);
你没有。您仍然在异步等待(因此,wait
),但没有使用线程,这意味着更好的可伸缩性
在async await
中,您可以获得性能提升,因为您的应用程序可以用更少的线程执行相同的操作,或者用相同的线程执行更多操作。要衡量这一点,您需要同时进行大量的异步
操作。只有这样,您才会注意到async
选项比同步选项更好地利用了CPU
资源
有关释放线程的详细信息,请参见此处在使用默认任务计划程序时,您仍然在线程池中以自己的线程运行每个任务。如果希望看到性能提升,则需要确保在同一线程上执行多个任务
另外,对于20个并行任务,您可能不会看到任何差异。尝试2000个任务。我知道我正在释放线程。以下是我无法想象的:如果我有一个4核处理器运行10个并行进程从队列中读取消息,那么在使用wait on
Task.Delay()时不应该是线程切换吗?我想使用已发布的线程。如果我为10个进程中的1个释放一个线程,为什么其他进程中没有一个使用该线程?@annemartijn当你说进程时,你是指线程吗?要改进async Wait的使用,您需要同时让CPU和IO(或其他异步)工作(在您的应用程序中)。这样,当一个线程在IO上被“阻塞”时,它可以去做其他CPU工作,而不是无所事事地等待。@annemartijn你没有错。使用“无线程异步”允许您同时执行更多IO(或异步)调用,因为它不会耗尽资源,线程可以同时执行CPU工作。这就是可伸缩性的含义。@annemartijn事实并非如此。当一个线程被阻塞时(例如使用thread.Sleep),CPU会将其切断并进行上下文切换。此外,您有4个以上的线程,如果需要,线程池可以创建更多线程。是的。异步不会缩短异步操作。需要多长时间就多长时间。但它释放了线程,所以您可以启动更多异步操作或使用CPU时间。