Search code examples
c#async-awaitvaluetask

Is there any sense to return ValueTask from method that internally awaits some Tasks


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?


Solution

  • 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 ValueTasks.

    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.