Expose HTTP.sys kernel response buffering control for HttpListener on Windows#124720
Open
karimsalem1 wants to merge 3 commits intodotnet:mainfrom
Open
Expose HTTP.sys kernel response buffering control for HttpListener on Windows#124720karimsalem1 wants to merge 3 commits intodotnet:mainfrom
karimsalem1 wants to merge 3 commits intodotnet:mainfrom
Conversation
Contributor
|
Tagging subscribers to this area: @karelz, @dotnet/ncl |
Member
AppContext switches are de-facto public APIs, just a different kind. |
ManickaP
reviewed
Feb 23, 2026
src/libraries/System.Net.HttpListener/tests/HttpResponseStreamTests.Windows.cs
Outdated
Show resolved
Hide resolved
ManickaP
reviewed
Feb 23, 2026
Member
ManickaP
left a comment
There was a problem hiding this comment.
One comment otherwise LGTM. I'll await the manual validation results.
Thanks!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR adds an opt-in
AppContextswitch to enable kernel response buffering in HttpListener (Windows implementation only). When enabled, the flagHTTP_SEND_RESPONSE_FLAG_BUFFER_DATAis set on all calls toHttpSendHttpResponseandHttpSendResponseEntityBody(consistent with Win32 docs). This mirrors the behavior for setting theHttpSysOptions.EnableKernelResponseBufferingflag in ASP.NET HTTP.sys code.Motivation in issue #123425.
Sample usage:
Notes:
HttpListenerandHttpResponseStream, and consolidated existing Windows-only tests there for consistency.Repro and validation
Setup:
Client uses HttpClient to send requests to the server and measures total latency. Server is running HttpListener and returns 7MB responses while varying the server-side response buffer size (from 32KB to 7MB). Server also records avg timing per individual response Write() call.
Benchmark
Kernel Buffering Disabled (Existing Behavior)
Kernel Buffering Enabled (New Behavior)
Write()time drops significantly (158,414 µs → 4,589 µs at 32 KB).These results confirm that without kernel buffering, small writes cause RTT amplification. Enabling kernel buffering eliminates small-write fragmentation over the wire and dramatically reduces latency.
Packet Capture
Packet analysis
Without kernel buffering, when the server sends a 7MB response using a 32KB buffer, packet capture shows that each server Write() results in a 32KB TCP segment (Length=32768, [PSH, ACK]). Each segment is transmitted approx. 1 RTT apart (~0.158s matching Azure-advertised RTT b/w the two regions). Transmission is effectively ACK-gated.
E2E the request takes ~34s:
With kernel buffering enabled, the TCP stack transmits large bursts of packets rather than one per RTT.
E2E latency dropped from ~34s to ~1s (first request ~1.9s due to TCP slow start, subsequent requests stabilize at ~0.95s).
TCP stream graph
The diff in behavior is best visualized using the Stevens TCP stream graph:
Without kernel buffering, the graph shows each ~32 KB increment in response transmission is separated by approx. one RTT. The slope is shallow (slow rate of growth) and evenly spaced.
With kernel buffering enabled, the slope becomes significantly steeper. Multiple segments are transmitted back-to-back before the next RTT boundary.
This visualizes the core issue: without buffering, small writes are RTT-amplified. With buffering, HTTP.sys aggregates response data in kernel space and transmits in large bursts, eliminating per-write RTT pacing.
Repro code
Init HttpListener with EnableKernelResponseBuffering switch
Server multi-write response routine
Thanks @ManickaP for all the help!