Slide 30
Slide 30 text
Why Streams Are Bad: Reason 2
async Task WriteToStreamAsync(Stream stream)
{
// So, it would be beneficial to add a buffer using BufferedStream, right?
using (var buffer = new BufferedStream(stream))
{
while (messages.TryDequeue(out var message))
{
await buffer.WriteAsync(message.Encode());
}
}
}
If the Stream is already Buffered, unnecessary allocation
would contradict the intent of "reducing allocation."
Being buffered means that in most cases (provided the buffer is not
overflowing) calls can be synchronous. If a call is synchronous, making
an asynchronous call is wasteful.
Public Task WriteAsync (byte[] buffer, int offset, int count);
public ValueTask WriteAsync (ReadOnlyMemory buffer);
Due to historical circumstances, Streams (and Sockets) have APIs that return a Task
and others that return a ValueTask, with similar parameters and the same name. If you
use an API that returns a Task, there's a chance you might inadvertently generate
unnecessary Task allocations. Therefore, always use a ValueTask call.
Fortunately, in the case of BufferedStream, the allocation itself does not occur because it
returns Task.CompletedTask for synchronous operations. However, there is a cost
associated with calling await. Regardless of whether it is ValueTask, waste is waste.