-
Notifications
You must be signed in to change notification settings - Fork 851
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enable zero-byte reads in streaming & WebSocket scenarios #1325
Comments
To get the full benefit out of zero-byte reads, we need runtime changes to enable them on the HttpClient response streams. The memory usage of YARP per 1000 WebSockets:
The main footprint is taken up by various Note that even the "current" already includes Kestrel zero-byte read improvements with SslStream. VS memory usage reports for each of the above 8 scenarios: https://1drv.ms/u/s!AtN8Uab8waEXje4ucv87PFavDX3Fcg?e=Tkffqp cc: @davidfowl Note: This applies to all requests, nothing here is WebSocket specific. |
Any way we could do this in a patch of 6.0? |
How could YARP take a dependency on a patch in the runtime? We would need an approach that still works if the patch isn't there. |
YARP doesn't need to take a dependency on the patch (I don't see why that matters). It's about consumers being able to get a bigger benefit when those changes are available. |
If the change ends up being small, low risk, and impactful. We should start with changes in main and go from there. |
See also dotnet/runtime#61223 (comment) -- in particular bullet (2) on that comment. We should probably split out a separate issue specifically to track zero-byte read support on response streams (including RawConnectionStream since that's used by websockets), since this should be straightforward to do and adds clear value for YARP scenarios and others. |
I added an issue specifically to track this: dotnet/runtime#61475 |
@davidfowl It looks like YARP needs to call ReadAsync differently if the fix is present or not in HttpClient's response stream. Right @MihaZupan? |
We can always try to perform 0 byte reads, but if the underlying stream doesn't support them it just means we will waste a few cycles to return the buffer only to rent it back right away. If we know that they won't be supported (<= 5.0), we can avoid trying at all, but functionally it would be fine either way. |
I think you could even address this by doing the following: (1) Issue 0 byte read, but don't await it In the case where the underlying stream doesn't support 0 byte read, the 0 byte read will always complete immediately and you'll never release the buffer. In the case where the underlying stream does support 0 byte read, you will also benefit because if there's more data available right now, the 0 byte read will complete immediately and you won't need to release/reacquire the buffer. |
Changes on runtime's side: dotnet/runtime#61913 |
The StreamCopier is used today for the request body, response body, as well as upgrade request and response streams. It rents a 64kb buffer per direction per request.
reverse-proxy/src/ReverseProxy/Forwarder/StreamCopier.cs
Line 19 in d3a185a
This is good for throughput, but not so good for scale. Streaming and WebSocket requests may spend long periods idle, holding onto 128kb of memory per connection.
In .NET 6 there was a lot of work to enable Zero-byte reads, allowing the caller to pass in empty buffers and wait to be notified of data before allocating. https://twitter.com/davidfowl/status/1451230807197040649?s=20
See where we can apply a similar pattern in YARP.
The text was updated successfully, but these errors were encountered: