Skip to content

QUIC: Reuse QuicStream instances on a connection #49972

@JamesNK

Description

@JamesNK

In Kestrel we want to reduce per-request HTTP/3 allocations to the minimum possible. Ideally that would be zero.

With HTTP/1.1 and HTTP/2 Kestrel is able to reuse per-request instances. For example, after a HTTP/2 request is gracefully completed (i.e. wasn't aborted and finished writing a frame with the close stream bit set) the stream is returned to a pool on the connection. Future requests on the connection will reuse the pooled stream by reseting it back to its initial state instead of creating a new one. This is discussed in a blog post.

At the moment a new QuicStream is created for each HTTP/3 request on a connection:

public class QuicConnection
{
    // Existing
    QuicStream OpenUnidirectionalStream();
    QuicStream OpenBidirectionalStream();
    ValueTask<QuicStream> AcceptStreamAsync();

    // New?
    void ReturnCompletedStream(QuicStream stream);
}

Support should be added to System.Net.Quic for optionally returning a QuicStream back to the connection when an app is no longer using it. The instance can then be reused by one of the factory methods above.

Extra things to consider:

  • Validate QuicStream is in a valid state before pooling it.
  • Maximum number of pooled streams. In Kestrel there is a max of 100 HTTP/2 pooled streams allowed on a connection. I don't think this needs to be configurable.
  • Remove unused streams after a certain amount of time. In Kestrel the HTTP/2 pooled streams on a connection are removed if not used within a certain amount of time. In place so idle connections don't unnessarily hold onto memory. I don't think this needs to be configurable.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions