Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Performance of multiple awaits compared to Task.WhenAll

General Information

I want to improve the performance of a program issuing multiple HTTP requests to the same external API endpoint. Therefore, I have created a console application to perform some tests. The method GetPostAsync sends an asynchronous HTTP request to the external API and returns the result as a string.

private static async Task<string> GetPostAsync(int id)
{
    var client = new HttpClient();
    var response = await client.GetAsync($"https://jsonplaceholder.typicode.com/posts/{id}");
    return await response.Content.ReadAsStringAsync();
}

Additionally, I have implemented the methods below to compare the execution time of multiple calls to await and Task.WhenAll.

private static async Task TaskWhenAll(IEnumerable<int> postIds)
{   
    var tasks = postIds.Select(GetPostAsync);
    await Task.WhenAll(tasks);
}

private static async Task MultipleAwait(IEnumerable<int> postIds)
{
    foreach (var postId in postIds)
    {
        await GetPostAsync(postId);
    }
}

Test Results

Using the integrated Stopwatch class, I have measured the timings of the two methods and interestingly enough, the approach using Task.WhenAll performed way better than its counterpart:

Issue 50 HTTP requests

  1. TaskWhenAll: ~650ms
  2. MultipleAwait: ~4500ms

Why is the method using Task.WhenAll so much faster and are there any negative effects (i.e exception handling) when choosing this approach over the other?

like image 203
prd Avatar asked Apr 12 '19 16:04

prd


People also ask

What is the use of task WhenAll?

WhenAll(Task[])Creates a task that will complete when all of the Task objects in an array have completed.

Does async await improve performance?

C# Language Async-Await Async/await will only improve performance if it allows the machine to do additional work.

Is task WhenAll multiple threads?

Parallel. ForEach is multiple threads solution while Task. WhenAll will probably share threads. If tasks share the same thread, they are just pieces of the thread and will need more time to complete the tasks.

Does WhenAll run in parallel?

WhenAll() method in . NET Core. This will upload the first file, then the next file. There is no parallelism here, as the “async Task” does not automatically make something run in in parallel.


1 Answers

Why is the method using Task.WhenAll so much faster

It is faster because you are not awaiting GetPostAsync. So actually every time you await client.GetAsync($"https://jsonplaceholder.typicode.com/posts/{id}"); the control will be returned to the caller which then can make another HTTP request. If you consider that HTTP request is much longer than creating the new client you effectively have the parallelism by running multiple HTTP requests in parallel. The WhenAll will just create a suspension point and wait for all tasks to finish.

With the multiple await approach, you make HTTP requests sequentially one by one by await GetPostAsync(postId) from foreach loop. You start the task but at the same time, you make a suspension point and wait for it to finish.

are there any negative effects (i.e exception handling, etc.) when choosing this approach over the other?

There are no negative effects, using await/async pattern handling exception become just, as usual, using try-catch block. WhenAll will aggregate all exception from each task which is in Faulted state.

like image 169
Johnny Avatar answered Oct 19 '22 23:10

Johnny