client: set TCP_NODELAY on the default connector - #7
Merged
Conversation
The default client stack builds an HttpConnector without disabling Nagle's algorithm. Requests are small and each waits for its response, which is the pattern Nagle delays. It is most visible on long-lived streams carried over the connection. A request/response protocol running inside a port-forwarded stream stalls on delayed ACKs, adding tens of milliseconds to a fraction of its exchanges.
aviramha
marked this pull request as ready for review
August 5, 2026 11:43
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.
Draft, against our fork's
main. Branched fromfork/main, which is level with upstreamkube-rs/kubeand keeps thePortforwarder::take_streampatch that mirrord depends on.What
impl TryFrom<Config> for ClientBuilderbuilds the connector withHttpConnector::new()andenforce_http(false), but neverset_nodelay(true). Every client built that way runs with Nagle's algorithm enabled.Why
Requests are small and each waits for its response, which is the pattern Nagle delays. It matters most for long-lived streams carried over the connection: a request/response protocol running inside a port-forwarded stream stalls on delayed ACKs.
mirrord reaches its in-cluster agent over
Api::portforward, so a sequential protocol tunnelled through that stream pays the stall.kubectldoes not show this, because it sets the option on its own connections.Measurement
Measured in mirrord, whose agent connection is a port-forwarded stream, with a workload issuing sequential requests over it:
set_nodelay~2.3x lower latency and ~33x lower tail. The 41 ms figure is the delayed-ACK timer.
The effect is concurrency-dependent, as expected for this mechanism: the stall needs the connection to fall idle between exchanges, so the gain is largest at low concurrency and fades as concurrent traffic keeps the connection busy and ACKs ride along with data.
Risk
One line, and it only disables an optimisation that trades latency for fewer packets. Applications sending many tiny writes in sequence will emit more packets. For an API client whose traffic is request/response that is the right trade.