Skip to content

Add optional maximum capacity to buffer writers#287

Open
petrroll wants to merge 1 commit into
dotnet:developfrom
petrroll:feature/buffer-max-capacity
Open

Add optional maximum capacity to buffer writers#287
petrroll wants to merge 1 commit into
dotnet:developfrom
petrroll:feature/buffer-max-capacity

Conversation

@petrroll

@petrroll petrroll commented Jul 8, 2026

Copy link
Copy Markdown

Motivation

Frequently you want to buffer but want to be sure it won't each unnecessary too much memory, have some (even if high) upper ceiling. This PR implements in the less impactful way. It's not limit for writing, it's a limit for sizing the buffer.

Not a strict one (as pool can give you bigger) but somewhat guaranteeing you won't OOM. Implemented this way it has almost no perf impact and doesn't complicate the usage much.

If desired it can be tightened up to either strictly limite the buffer / writes (so that it's guaranteed not to get bigger capacity buffer; thus also write more). I don't think it's needed (not for my usecase at least) but could be useful for some.

Summary

Adds an optional MaxCapacity limit to the pooling buffer writers so buffer growth can be bounded.

MaxCapacity is now available on:

  • PoolingBufferWriter<T> and PoolingArrayBufferWriter<T> (via the shared BufferWriter<T> base class)
  • BufferWriterSlim<T>

When a write requires the internal buffer to grow beyond MaxCapacity, InsufficientMemoryException is thrown — consistent with the existing Array.MaxLength ceiling and the other max-size guards across the library. The check lives in the shared grow path (IGrowableBuffer<T>.GetBufferSize); when the write still fits, the growth request is clamped to MaxCapacity. By default the maximum capacity is unbounded.

Notes

  • The value bounds the growth request, not the exact physical buffer size: because buffers are rented from a pool, the allocator may round up to the next bucket, so the actual Capacity can be slightly larger. This is documented in the API remarks.
  • SparseBufferWriter<T> is intentionally not affected — it grows by appending independent chunks and does not use the shared grow path.

Tests

Added unit tests covering growth within the limit, growth beyond the limit (throws), exact-boundary clamping, validation of invalid values, and the unbounded default.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant