I have an async method that looks approximately like this:
async Task<int> ParseStream()
{
var a = await reader.ReadInt32();
var b = await reader.ReadInt32();
return a + b;
}
This method is going to work synchronously most of the time as data is already ready.
So looks like good idea to replace return type with ValueTask to reduce allocations.
But this calls reader.ReadInt32()
return Task.
So the question is: is there any sense to return ValueTask from method that internally awaits some Tasks?
Changing the signature of your method to return a ValueTask
instead of Task
:
async ValueTask<int> ParseStreamAsync()
{
var a = await reader.ReadInt32Async();
var b = await reader.ReadInt32Async();
return a + b;
}
...has the advantage that callers invoking your method will avoid an object allocation in case that both calls to reader.ReadInt32Async
will complete synchronously. But this may not be a great advantage because the two calls to reader.ReadInt32Async
may still allocate a Task
object each, depending on how this method is implemented. It is theoretically possible that some common Task<Int32>
return values will be cached, but in practice not very probable. It would be different if the return value was Task<bool>
, were caching the only two possible values would be cheap. Caching Task<TResult>
objects was the only way available for reducing allocations before the introduction of ValueTask
s.
So by using ValueTask
instead of Task
you can reasonably expect that you'll reduce the object allocations from 3 to 2 on each invocation, which is not very impressive, but not negligible either.