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

时间:2014-04-29 08:47:51

标签: c# task-parallel-library async-await performance-testing 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);
    }
}

异步消息处理

Task.Delay()上使用等待,因此应释放当前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()使用10,100,10000或更多消息填充所有队列。

编辑2

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

编辑3(修复)

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

2 个答案:

答案 0 :(得分:8)

使用async-await并不会加快执行单个操作所需的时间,这只是意味着您没有让线程无所事事

在你的情况下,Task.Delay无论如何都会花一秒时间:

Task.Delay(1000).Wait();

拥有一个线程,在此处等待第二个结束:

await Task.Delay(1000);

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

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


有关释放线程There Is No Thread

的更多信息

答案 1 :(得分:2)

当您使用默认任务调度程序时,您仍然在线程池中运行其自己的线程中的每个任务。如果你想看到性能损失,你需要确保在同一个线程上执行几个任务。

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