When using Parallel.ForEach, would converting any DB or Api calls to async methods improve performance?
A bit of background, I currently have a console application that sequentially loops through a bunch of files and for each one calls an API and makes some DB calls. The main logic looks like this:
foreach (file in files)
{
ReadTheFileAndComputeAFewThings(file);
CallAWebService(file);
MakeAFewDbCalls(file);
}
Currently all of the DB and web service calls are synchronous.
Changing the loop to use Parallel.ForEach
has given me a massive performance increase, just as you would expect.
I am wondering if I kept the Parallel.ForEach
call there, and inside the loop, change all of the webservice calls to be async (eg, HttpClient.SendAsync
) and DB calls to be async (using Dapper, db.ExecuteAsync()
) - would that increase performance of the application by allowing it to re-use threads? Or would it effectively do nothing as Parallel.ForEach
is taking care of the thread allocation anyway?
The answer is No. Asynchrony offers scalability, not performance. It allows to do the same job with less threads, and so with less memory (each blocked thread = 1 MB of wasted memory).
It’s important to keep in mind, though, that asynchronicity is not a performance optimization for an individual operation. Taking a synchronous operation and making it asynchronous will invariably degrade the performance of that one operation, as it still needs to accomplish everything that the synchronous operation did, but now with additional constraints and considerations.
It should be noted that the Parallel.ForEach
API cannot be used with asynchronous body
delegate. Using async
with this API is a bug. The correct API to use when you want to parallelize asynchronous operations is the Parallel.ForEachAsync
, available from .NET 6 and later.