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.
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);
}
}
Uses await on Task.Delay()
, so should release current Thread
static async Task ProcessMessageAsync(Message message)
{
await Task.Delay(1000);
BurnCpu();
}
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?
I'm measuring overall time using stopWatch.ElapsedMilliseconds
. I Fill all queues using FillAllQueuesWithMessages()
with 10, 100, 10000 or more messages.
ReceiveMessagesForQueue()
returns Task
instead of void
now.
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.
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.
Your Ultimate async / await Tutorial in C# Increase the performance and responsiveness of your application, particularly when you have long-running operations that do not require to block the execution. In this case, you can perform other work while waiting for the result from the long running task.
For applications with many tasks, programmers can consider using async programming. It allows one or more tasks to progress independently, rather than sequentially. The user benefits from increased responsiveness and improved overall performance.
I found out that running async-await can be much slower in some scenarios. But if I click on the 'both' button, the 'await' version is ~3-4 times slower than the promises version.
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
You're still running each task in its own thread from the thread pool - as you're using the default task scheduler. If you want to see performance imporvement, you'll need to make sure several tasks are performed on the same thread.
Also, with 20 parallel tasks, you're probably not going to see any difference. Try it with 2,000 tasks.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With