Meziantou.Framework.PooledMemoryStream 2.0.7

Prefix Reserved
There is a newer version of this package available.
See the version list below for details.
dotnet add package Meziantou.Framework.PooledMemoryStream --version 2.0.7
                    
NuGet\Install-Package Meziantou.Framework.PooledMemoryStream -Version 2.0.7
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Meziantou.Framework.PooledMemoryStream" Version="2.0.7" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Meziantou.Framework.PooledMemoryStream" Version="2.0.7" />
                    
Directory.Packages.props
<PackageReference Include="Meziantou.Framework.PooledMemoryStream" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Meziantou.Framework.PooledMemoryStream --version 2.0.7
                    
#r "nuget: Meziantou.Framework.PooledMemoryStream, 2.0.7"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Meziantou.Framework.PooledMemoryStream@2.0.7
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Meziantou.Framework.PooledMemoryStream&version=2.0.7
                    
Install as a Cake Addin
#tool nuget:?package=Meziantou.Framework.PooledMemoryStream&version=2.0.7
                    
Install as a Cake Tool

Meziantou.Framework.PooledMemoryStream

PooledMemoryStream is a MemoryStream whose storage is a chain of pooled byte arrays rented from a process-wide pool shared by all instances. Growing the stream never reallocates and copies a single backing array — new pooled blocks are appended to the chain. Blocks are only ever rented in a small set of discrete sizes (Small / Medium / Large), so the pool stays effective. It also implements IBufferWriter<byte>.

Basic usage

PooledMemoryStream is in the Meziantou.Framework namespace.

using var stream = new PooledMemoryStream();
stream.Write("Hello, "u8);
stream.Write("World!"u8);

stream.Position = 0;
using var reader = new StreamReader(stream);
Assert.Equal("Hello, World!", reader.ReadToEnd());

// The pooled buffers are returned to the shared pool when the stream is disposed.

Use it as an IBufferWriter<byte>

IBufferWriter<T> is in the System.Buffers namespace, and Utf8JsonWriter in System.Text.Json.

using var stream = new PooledMemoryStream();

// PooledMemoryStream implements IBufferWriter<byte> (explicit), so it can be passed where one is expected.
IBufferWriter<byte> writer = stream;
await using (var json = new Utf8JsonWriter(writer))
{
    json.WriteStartObject();
    json.WriteString("message", "hello");
    json.WriteEndObject();
}

var bytes = stream.ToArray();
Assert.Equal("""{"message":"hello"}"""u8.ToArray(), bytes);

Data written through IBufferWriter<byte> is appended at the end of the stream; after Advance, Position is moved to the new end.

Configure the buffer sizes

var options = new PooledMemoryStreamOptions
{
    // Any number of strictly ascending tiers (bytes). Small streams use the smallest size and
    // grow through the larger ones; buffers bigger than the largest tier round up to a multiple of it.
    BufferSizes = [4 * 1024, 128 * 1024, 1024 * 1024, 10 * 1024 * 1024], // 4 KiB / 128 KiB / 1 MiB / 10 MiB
    MaxRetainedBytesPerBucket = 64L * 1024 * 1024,
    ClearOnReturn = false,
};

using var stream = new PooledMemoryStream(options);

PooledMemoryStreamOptions becomes immutable (frozen) the first time it is used to create a stream; after that, setting any property throws InvalidOperationException. The shared PooledMemoryStreamOptions.Default is always frozen. Configure all properties before passing the options to a stream.

Notes

  • The byte arrays (including the array returned by GetBuffer() / TryGetBuffer(), and the spans/memory returned by the IBufferWriter<byte> members) are owned by the stream and are returned to the shared pool on Dispose. Do not use them after the stream is disposed.
  • The array returned by GetBuffer() / TryGetBuffer() is never returned to the shared pool before Dispose, so another stream cannot rent it while you hold it. Like with MemoryStream, it stays the stream's storage (shrinking with SetLength or Capacity keeps it, so later writes overwrite it) until a later GetBuffer() / TryGetBuffer() call consolidates several blocks into a new array; the old array then stays valid but no longer reflects the stream contents.
  • GetBuffer() returns the whole underlying array, not just the first Length bytes. Only [0, Length) is meaningful; the rest is zeroed before the array is handed out, so it never exposes data written by another stream. The spans returned by the IBufferWriter<byte> members are uninitialized, as usual for a buffer writer.
  • Because the storage is a chain of blocks rather than a single array, the stream is not bounded by Array.MaxLength: it can hold as many bytes as memory allows. The members that must produce a single array (ToArray(), GetBuffer(), TryGetBuffer()) are still bounded by it and throw an InvalidOperationException on a longer stream. Capacity is an int inherited from MemoryStream, so its getter is clamped to int.MaxValue.
  • The instance is not thread-safe (like MemoryStream); the shared pool is.
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed.  net11.0 is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.
  • net11.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.9 0 11/8/2026
2.0.8 160 10/29/2026
2.0.7 108 10/28/2026
2.0.6 98 10/21/2026
2.0.5 224 9/13/2026
2.0.4 96 9/11/2026
2.0.3 130 9/6/2026
2.0.2 128 9/3/2026
2.0.1 121 9/3/2026
2.0.0 361 7/5/2026
1.0.2 146 6/13/2026
1.0.1 147 6/7/2026
1.0.0 210 5/29/2026