Let's say I have 3 methods as follows:
public async Task<int> CalculateData(int index, int trustLevel, string type)
{
var x = await CalculateBaseScore(index, type);
return ComplexProcess(x, trustLevel);
}
public async Task<int> CalculateBaseScore(int index, string type)
{
var conn_string = "...";
var sql = "...";
var param = new { Index = index, Type = type };
using (var conn = new SqlConnection(conn_string))
{
var db_output = await conn.ExecuteScalarAsync<int>(sql, param: param);
return db_output;
}
}
public int CalculateBaseScore(int index, int trustLevel)
{
//Omitted
}
As you can see, 2 of them use async-await.
In Stephen Cleary's introduction to async-await, it's said that
If you can write it without await, then you should write it without await, and remove the async keyword from the method. A non-async method returning Task.FromResult is more efficient than an async method returning a value.
In this case, will a Dapper-made database call qualify as a method I can write without async-await and simply return a Task<int>
object? Will I get any benefits in performance or other aspects if I change it to this?
public async Task<int> CalculateData(int index, int trustLevel, string type)
{
var x = await CalculateBaseScore(index, type);
return ComplexProcess(x, trustLevel);
}
public Task<int> CalculateBaseScore(int index, string type)
{
var conn_string = "...";
var sql = "...";
var param = new { Index = index, Type = type };
using (var conn = new SqlConnection(conn_string))
{
var db_output_task = conn.ExecuteScalarAsync<int>(sql, param: param);
return db_output_task;
}
}
public int CalculateBaseScore(int index, int trustLevel)
{
//Omitted
}
See tht in the second example, I omitted the async-await keywords on CalculateBaseScore
and simply returned the Task
object.
Regarding the second implementation without async-await:
public Task<int> CalculateBaseScore(int index, string type)
{
var conn_string = "...";
var sql = "...";
var param = new { Index = index, Type = type };
using (var conn = new SqlConnection(conn_string))
{
var db_output_task = conn.ExecuteScalarAsync<int>(sql, param: param);
return db_output_task;
}
}
...will give you a performance boost of around 1 μsec per invocation. In other words it will save you a whole second of CPU time after invoking it 1,000,000 times. These are the good news.
The bad news are that all these 1,000,000 invocations will result to an ObjectDisposedException
, because the SqlConnection
will be disposed prematurely, immediately after the creation of the Task
.
Does it worth it? I'd say no. Keeping it simple will save you more time in the long run.