Skip to content

Excessive per-connection memory cause by channel #4057

@howardjohn

Description

@howardjohn

This is not a bug or anything, or even really behaving wrong, just an optimization potential.

Each HTTP/1.1 channel allocates an obvious 8k from INIT_BUFFER_SIZE: usize = 8192; this is fine and expected (although perhaps could use some configuration for "many connections with small payloads/less stringent performance requirements").

However, there is another ~8kb allocated as well per connection that I don't think is desirable. Each connection gets an unbounded dispatch channel. This in turn creates a channel that has 32 blocks (https://github.com/tokio-rs/tokio/blob/8f81e0814bd121683ebdfa21b494d1b77fb36403/tokio/src/sync/mpsc/mod.rs#L140 https://github.com/tokio-rs/tokio/blob/8f81e0814bd121683ebdfa21b494d1b77fb36403/tokio/src/sync/mpsc/block.rs#L47).

Each http request is ~250b, giving us another ~8kb for the channel here.

While in theory the SendRequest API does allow pushing a bunch of requests at once, practically speaking most are using this in front of a pooling client (hyper_util or otherwise) which is going to only send requests that are ready. So I would think we don't need for most cases unbounded, nor a 32 block buffer.

A theoretical nice option here, that allows the strange case of sending multiple requests but optimizes the common case, would be to just have the channel not use 32 blocks (which I imagine is for performance reasons not relevant to us?). However, tokio doesn't expose any such option.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-clientArea: client.B-upstreamBlocked: needs a change in a dependency or the compiler.C-performanceCategory: performance. This is making existing behavior go faster.S-blockedStatus: blocked on something else.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions