When working with BinaryData and MemoryStream in .NET, you may need to convert stream data into a BinaryData instance. The typical approach using BinaryData.FromStream() copies the entire buffer, which impacts performance and increases memory allocations. A more efficient approach exists that avoids all memory copies.
#The problem with BinaryData.FromStream()
The standard way to create BinaryData from a stream is straightforward but comes with a performance cost:
C#
var stream = new MemoryStream();
stream.Write([1, 2, 3]);
stream.Seek(0, SeekOrigin.Begin);
// This requires a memory copy
var data = BinaryData.FromStream(stream);
When you call BinaryData.FromStream(), the method reads the stream and copies its contents into a new buffer. For large streams or performance-critical applications, this additional copy can be wasteful.
#The zero-copy approach
If you're working with a MemoryStream, you can access its underlying buffer directly and create a BinaryData instance without copying:
C#
var stream = new MemoryStream();
stream.Write([1, 2, 3]);
// This does not require a memory copy
var data = new BinaryData(stream.GetBuffer().AsMemory(0, (int)stream.Position));
This approach uses GetBuffer() to access the underlying byte array of the MemoryStream, then wraps it in a Memory<byte> slice that represents only the written portion. The BinaryData constructor accepts ReadOnlyMemory<byte>, so the conversion happens implicitly.
Interestingly, the BinaryData implementation itself uses a similar optimization. Looking at the source code, BinaryData.FromStream() already checks whether the stream is a MemoryStream and calls TryGetBuffer() to avoid copying when possible.
Do you have a question or a suggestion about this post? Contact me!