简体   繁体   中英

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 test which one has the shortest execution time.

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 execution time 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 (ie exception handling, etc.) when choosing this approach over the other?

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 (ie 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM