satish
Posted on August 15, 2020
System.Threading.Task is one of the de facto best practices for .net programming for async programming for all these years. C# 7.0 has added a cherry on top of it with Value Task for optimizing performance and abstraction.
Performance benefit
To illustrate the benefit in performance, Let's call an API to return the restaurant data for a particular city and cache the result. I have used caching here to show that there is a mix of synchronous and asynchronous code.
[MemoryDiagnoser]
public class ZomatoCitySearch
{
private static IDictionary<string, SearchSuggestion> CacheList = new Dictionary<string, SearchSuggestion>();
[Benchmark]
public async Task<SearchSuggestion> SearchCity()
{
if (CacheList.ContainsKey("ben"))
{
return CacheList["ben"];
}
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("user-key","*****");
var response = await client.GetAsync(
"https://developers.zomato.com/api/v2.1/cities?q=ben");
var content = await response.Content.ReadFromJsonAsync<SearchSuggestion>();
CacheList["ben"] = content;
return content;
}
[Benchmark]
public async ValueTask<SearchSuggestion> SearchCityWithValueTask()
{
if (CacheList.ContainsKey("new"))
{
return CacheList["new"];
}
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("user-key","***");
var response = await client.GetAsync(
"https://developers.zomato.com/api/v2.1/cities?q=new");
var content = await response.Content.ReadFromJsonAsync<SearchSuggestion>();
CacheList["new"] = content;
return content;
}
}
I ran the benchmark test with the Value Task and Task, Here is what the benefit
As per the result, we are using half the memory of Task and in a high-performance environment that can a lifesaver.
Value Task being a struct helps avoid the creation of the object also the internal state machine when the code is executing the synchronous way.
Abstraction
One of the problems with using Task in the abstraction is we will force the implementation to use the asynchronous code where it may not be required.
For example, If we create an ICacheprovier interface with the async Get method, We will force the same to Implemented by MemoryCacheprovider too. With the advent of ValueTask, this can be avoided and memory cache doesn't need to cost of Task creation with this model
Posted on August 15, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.