2

At work we were discussing should we use in our ASP.NET Core application with 20 users synchronous fast queries (such as EF's dbContext.Table.First()) instead of the async versions due to additional time to create another thread for the async operation.

I benchmarked both versions.

The application runs on a Windows 10 computer (i5, 16 Gb, Current timer interval: 0.999 ms). The DB is on another computer in Docker in local network.

public async Task<DailyExchangeRate> GetExchangeRateAsync(int currencyId, DateTime date)
{
    return await dbContext.DailyExchangeRates
            .Where(dr => dr.CurrencyId == currencyId)
            .FirstOrDefaultAsync(dr => dr.Date == date.Date);
}

public DailyExchangeRate GetExchangeRate(int currencyId, DateTime date)
{
    return dbContext.DailyExchangeRates
            .Where(dr => dr.CurrencyId == currencyId)
            .FirstOrDefault(dr => dr.Date == date.Date);
}

The results are in Stopwatch.Ticks (the last column): The results in ticks

Why the async version is faster?

GSerg
  • 76,472
  • 17
  • 159
  • 346
FireShock
  • 1,082
  • 1
  • 15
  • 25
  • 4
    `due to additional time to create another thread` - [no](https://stackoverflow.com/q/17661428/11683). – GSerg May 23 '20 at 09:44

2 Answers2

4

instead of the async versions due to additional time to create another thread for the async operation

Why do you think that for each async operation there will have to be a new thread created?

There is already a thread pool associated with the server, it's just the matter of 'unblocking' so to speak a given thread, and use it to process another request since the call to the database is async - there is no need to block until the SQL query completes and comes back.

When it comes to the connection to your database, there is a db Connection pool which EF handles and using FirstOrDefaultAsync will also improve the performance a bit since, it may use the same connection to processes few db calls, instead of using one connection and wait for the result from db - in the FirstOrDefault sync call

Jakub Kozera
  • 3,141
  • 1
  • 13
  • 23
4

async-await is not about making each operation faster but about increasing the availability of a system by reusing threads. If you have enough threads available, blocking will be faster that switching.

Your test is flawed because you're including the JIT compilation in the measure (see the time taken for the first and second requests in comparison with the following ones). You need to warm-up the execution and throw out the outliers. See how BenchmarkDotNet does it.

Try setting the size of the thread pool to a small number and invoke the methods concurrently to see the difference.

Paulo Morgado
  • 14,111
  • 3
  • 31
  • 59