Skip to content

perf: disable Nagle's algorithm on scheduler connections - #2798

Merged
andygrove merged 1 commit into
apache:mainfrom
andygrove:perf-scheduler-tcp-nodelay
Nov 7, 2026
Merged

andygrove merged 1 commit into
apache:mainfrom
andygrove:perf-scheduler-tcp-nodelay

Conversation

@andygrove

@andygrove andygrove commented Nov 7, 2026 •

Copy link
Copy Markdown
Member

Which issue does this PR close?

No single issue. Split out of #2792. Related: #2520 (performance review tracking).

Rationale for this change

The scheduler serves gRPC through axum, which, unlike tonic's own server, leaves Nagle's algorithm on for accepted connections. A poll response is several small HTTP/2 frames, so the later ones wait for the executor's delayed ACK, about 40 ms per poll on Linux. Under pull scheduling that is added to every task launch, so a stage of N waves pays N x 40 ms. TPC-H q2 at 128 partitions spent about 2 s of its 5.6 s waiting. At 128 partitions on one machine (TPC-H SF100), all of #2792 takes 148 s against 204 s on main, mostly from this change.

What changes are included in this PR?

TCP_NODELAY is set on every connection the scheduler accepts, via ListenerExt::tap_io. A failure to set it logs a warning and the connection proceeds. The standalone scheduler serves tonic from a pre-bound listener, which ignores the builder's tcp_nodelay, so it gets TcpIncoming::with_nodelay(true), as the standalone executor already does.

No test: the effect is a socket option on accepted connections, and a test needs a real TCP socket.

Not covered: the scheduler's axum listener also sets no TCP keepalive, unlike the listeners made by create_grpc_server_incoming. That predates this change.

Are there any user-facing changes?

No config or API changes. Lower task-launch latency under pull scheduling.

The scheduler serves gRPC through axum, which, unlike tonic's own
server, leaves Nagle's algorithm on for accepted connections. A poll
response is several small HTTP/2 frames, so the later ones wait for the
executor's delayed ACK: about 40 ms per poll on Linux. Under pull
scheduling that is added to every task launch, so a stage of N waves
pays N x 40 ms; TPC-H q2 at 128 partitions spent about 2 s of its 5.6 s
waiting. Set TCP_NODELAY on every accepted connection.

The standalone scheduler serves tonic from a pre-bound listener, which
ignores the builder's tcp_nodelay, so set it there too.
@andygrove
andygrove force-pushed the perf-scheduler-tcp-nodelay branch from cf8c136 to aeadcff Compare November 7, 2026 17:07
@andygrove
andygrove marked this pull request as ready for review November 7, 2026 17:20

@milenkovicm milenkovicm left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like you're starting with infrastructure tuning. Thanks @andygrove

@andygrove
andygrove requested a review from comphead November 7, 2026 17:32
@andygrove
andygrove added this pull request to the merge queue Nov 7, 2026
@andygrove

Copy link
Copy Markdown
Member Author

Thanks for the review @milenkovicm

Merged via the queue into apache:main with commit bf90879 Nov 7, 2026
24 of 25 checks passed
@andygrove
andygrove deleted the perf-scheduler-tcp-nodelay branch November 7, 2026 17:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants