Add Span overrides to BufferedReadStream - #69067
Conversation
Override Read(Span<byte>) and Write(ReadOnlySpan<byte>) so callers using the span overloads no longer go through the base Stream fallback, which rents a pooled array and copies. MultipartReaderStream already reads through the span overload on every section read.
|
Thanks for your PR, @SimonCropp. Someone from the team will get assigned to your PR shortly and we'll get it reviewed. |
There was a problem hiding this comment.
🟡 Changes recommended
The current Read(byte[], int, int) refactor can introduce new ArrayPool rent/copy overhead for byte[] callers when the inner stream doesn’t override span, and the new dispatch/perf behavior should be covered by unit tests.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR adds Span/ReadOnlySpan overrides to Microsoft.AspNetCore.WebUtilities.BufferedReadStream so span-based callers avoid the base Stream fallback path that rents/copies, improving performance in scenarios like multipart parsing.
Changes:
- Add
BufferedReadStream.Read(Span<byte>)andBufferedReadStream.Write(ReadOnlySpan<byte>)overrides. - Refactor
Read(byte[], int, int)to delegate to the span overload. - Update
PublicAPI.Unshipped.txtto track the new overrides.
File summaries
| File | Description |
|---|---|
| src/Http/WebUtilities/src/BufferedReadStream.cs | Adds span overrides and refactors read logic to use them. |
| src/Http/WebUtilities/src/PublicAPI.Unshipped.txt | Records the new override members in the public API tracking file. |
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
Cover the span and array Read overloads draining buffered data before falling through to the inner stream, and Write(ReadOnlySpan<byte>) forwarding to the inner stream.
Forwarding the array overload through Read(Span<byte>) meant that with an empty buffer it called _inner.Read(Span<byte>), which falls back to Stream's rent-and-copy shim when the inner stream does not override it. Share the buffer drain in a helper and have each overload forward to the matching inner overload instead.
…inner overload Use an inner stream that counts calls to its array and span overloads so the tests fail if BufferedReadStream ever routes an array call through the span overload or vice versa, which would fall back to Stream's rent-and-copy shim on inner streams lacking the override.
Add Span overrides to BufferedReadStream
Description
Override Read(Span) and Write(ReadOnlySpan) so callers using the span overloads no longer go through the base Stream fallback, which rents a pooled array and copies. MultipartReaderStream already reads through the span overload on every section read.