ann*_*ijn 7 c# performance-testing task-parallel-library async-await c#-5.0
我有一个从多个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<Message>(queue.BeginReceive(), queue.EndReceive);
if (isAsync)
await ProcessMessageAsync(message);
else
ProcessMessage(message);
}
}
Run Code Online (Sandbox Code Playgroud)
使用等待Task.Delay(),所以应该释放当前Thread
static async Task ProcessMessageAsync(Message message)
{
await Task.Delay(1000);
BurnCpu();
}
Run Code Online (Sandbox Code Playgroud)
等等Task.Delay(),所以不应该释放当前Thread
static void ProcessMessage(Message message)
{
Task.Delay(1000).Wait();
BurnCpu();
}
Run Code Online (Sandbox Code Playgroud)
最后,结果是平等的.我在这里错过了什么吗?
我正在测量使用时间stopWatch.ElapsedMilliseconds.我使用FillAllQueuesWithMessages()10,100,10000或更多消息填充所有队列.
ReceiveMessagesForQueue()Task而不是void现在返回.
此测试确实显示了我现在的性能改进.我不得不BurnCpu()花更多的时间.虽然Task.Delay()被期待已久的,BurnCPU()可以使用发布的线程来处理.
使用async-await不会加快执行单个操作所需的时间,这只意味着您没有一个线程在等待什么都不做.
在你的情况下,无论如何,只Task.Delay需要一秒钟:
Task.Delay(1000).Wait();
Run Code Online (Sandbox Code Playgroud)
你有一个线程,在这里等待第二个结束:
await Task.Delay(1000);
Run Code Online (Sandbox Code Playgroud)
你没有.您仍在异步等待(因此await),但没有使用线程,这意味着更好的可伸缩性.
在async-await您获得性能提升时,因为您的应用程序可以使用更少的线程执行相同操作,或者使用相同的线程执行更多操作.要衡量您需要同时进行大量async操作.只有这样,您才会注意到该async选项CPU比同步选项更好地利用资源.
有关解冻螺纹的更多信息,这里有没有线程