Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
411 views
in Technique[技术] by (71.8m points)

c# - How to measure performance of awaiting asynchronous operations?

I have a Windows Service that reads from multiple MessageQueue instances. Those messagequeues all run their own Task for reading messages. Normally, after reading a message, the work of an I/O database is done. I've found articles claiming it's a good idea to use async on I/O operations, because it would free up threads. I'm trying to simulate the performance boost of using async I/O opertations in a Console application.

The Console application

In my test environment, I have 10 queues. GetQueues() returns 10 different MessageQueue instances.

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);
    }
}

Async message processing

Uses await on Task.Delay(), so should release current Thread

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

Sync message processing

waits on Task.Delay(), so shouldn't release current Thread

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

In the end, results are equal. Am I missing something here?

Edit 1

I'm measuring overall time using stopWatch.ElapsedMilliseconds. I Fill all queues using FillAllQueuesWithMessages() with 10, 100, 10000 or more messages.

Edit 2

ReceiveMessagesForQueue() returns Task instead of void now.

Edit 3 (fix)

This test does show me performance improvement now. I had to make BurnCpu() take more time. While Task.Delay() is being awaited, BurnCPU() can use the released thread to process.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Using async-await doesn't speed up the time it takes to execute a single operation, it just means that you don't have a thread waiting doing nothing.

In your case Task.Delay will take a second no matter what but here:

Task.Delay(1000).Wait();

You have a thread that sits and waits for the second to end while here:

await Task.Delay(1000);

You don't. You are still asynchronously waiting (hence, await) but no thread is being used which means better scalability.

In async-await you get the performance boost because your app can do the same with less threads, or do more with the same threads. To measure that you need to have a lot of async operations concurrently. Only then will you notice that the async option utilizes CPU resources better than the synchronous one.


More info about freeing threads here There Is No Thread


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...