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

标签 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() 上使用 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() 用 10、100、10000 或更多消息填充所有队列。

编辑2

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

编辑 3(修复)

这个测试确实显示了我现在的性能改进。我不得不让 BurnCpu() 花费更多时间。在等待 Task.Delay() 时,BurnCPU() 可以使用已释放的线程进行处理。

最佳答案

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

在你的情况下,Task.Delay 无论如何都需要一秒钟,但在这里:

Task.Delay(1000).Wait();

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

await Task.Delay(1000);

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

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


有关释放线程的更多信息,请点击此处 There Is No Thread

关于c# - 如何衡量等待异步操作的性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23359829/

相关文章:

c# - 使用 VS Code 在 ASP.NET Core 中进行本地化 - "No resources found"

c# - 为什么简单的多任务在多线程工作时不起作用?

c# - 延迟然后执行任务

javascript - 在 Typescript 中使用 AsyncIterator – 必需选项

c# - 异步/等待死锁

c# - SQLite 异步任务和 Wait 运算符 - 任务会以正确的顺序执行吗?

c# - 在浏览器中打开 .mht/.mhtml 文件

c# - C#中的动态类创建

c# - 在 .NET 应用程序中隐藏 SMTP 密码

c# - 并发问题: parallel writes