Skip to content

Optimize WebSocket receive path on pre-netstandard2.1 targets#1462

Draft
Copilot wants to merge 3 commits into
mainfrom
copilot/websocket-read-async-improvement
Draft

Optimize WebSocket receive path on pre-netstandard2.1 targets#1462
Copilot wants to merge 3 commits into
mainfrom
copilot/websocket-read-async-improvement

Conversation

Copilot AI commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

This change improves WebSocketMessageHandler.ReadCoreAsync for pre-netstandard2.1 TFMs by avoiding an unnecessary copy when the sequence memory can be exposed as an ArraySegment<byte>. It keeps existing behavior while reducing allocations/copy work on the hot read path used by both client and server WebSocket transports.

  • Read-path optimization (netfx / pre-2.1 branch)

    • Switched from always renting a temporary buffer and writing into the sequence, to first obtaining destination memory from contentSequenceBuilder.
    • If MemoryMarshal.TryGetArray(memory, out segment) succeeds, ReceiveAsync now reads directly into destination storage.
  • Fallback correctness when direct array access is unavailable

    • Retained pooled-array fallback for non-array-backed memory.
    • Receives into a bounded segment (new ArraySegment<byte>(rented, 0, memory.Length)), then copies only result.Count bytes into destination memory.
  • Buffer advancement alignment

    • Replaced Write(...) usage in the legacy branch with Advance(result.Count) after receive/copy, aligning mechanics with the modern branch.
Memory<byte> memory = this.contentSequenceBuilder.GetMemory(this.sizeHint);
if (MemoryMarshal.TryGetArray(memory, out ArraySegment<byte> segment))
{
    result = await this.WebSocket.ReceiveAsync(segment, cancellationToken).ConfigureAwait(false);
}
else
{
    byte[] rented = ArrayPool<byte>.Shared.Rent(memory.Length);
    try
    {
        result = await this.WebSocket.ReceiveAsync(
            new ArraySegment<byte>(rented, 0, memory.Length), cancellationToken).ConfigureAwait(false);
        rented.AsSpan(0, result.Count).CopyTo(memory.Span);
    }
    finally
    {
        ArrayPool<byte>.Shared.Return(rented);
    }
}
this.contentSequenceBuilder.Advance(result.Count);

Copilot AI and others added 2 commits June 12, 2026 19:45
Co-authored-by: AArnott <3548+AArnott@users.noreply.github.com>
Co-authored-by: AArnott <3548+AArnott@users.noreply.github.com>
Copilot AI changed the title [WIP] Improve websocket read async performance for netfx Optimize WebSocket receive path on pre-netstandard2.1 targets Jun 12, 2026
Copilot AI requested a review from AArnott June 12, 2026 19:51
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.

2 participants