Skip to content

perf(tcp): disable Nagle's algorithm on accepted connections#210

Open
EddieHouston wants to merge 1 commit intoBlockstream:new-indexfrom
EddieHouston:fix/tcp-nodelay
Open

perf(tcp): disable Nagle's algorithm on accepted connections#210
EddieHouston wants to merge 1 commit intoBlockstream:new-indexfrom
EddieHouston:fix/tcp-nodelay

Conversation

@EddieHouston
Copy link
Copy Markdown
Collaborator

@EddieHouston EddieHouston commented Apr 21, 2026

Disable Nagle's algorithm on accepted TCP connections

Set TCP_NODELAY on all accepted connections for both the Electrum RPC server (server.rs) and the REST HTTP server (rest.rs).

Why

Nagle's algorithm coalesces small outgoing segments, waiting up to 200ms for more data before flushing. On request/response protocols this interacts badly with TCP delayed ACKs on the peer: the server holds a small response waiting to batch it, while the client holds its ACK waiting for more data, producing an unnecessary stall on every round trip. Disabling Nagle ensures responses are sent immediately without waiting for the coalescing timer.

The Unix socket path in rest.rs is left unchanged — TCP_NODELAY is not applicable to Unix domain sockets.

Benchmark methodology

A BDK wallet sync (ElectrumBlockchain::sync, stop_gap=20, 2 descriptors) against a signet electrs node. The sync issues 204 sequential Electrum RPC calls on a single persistent TCP connection
(blockchain.scripthash.get_history ×200, blockchain.transaction.get ×2, blockchain.headers.subscribe ×1, blockchain.block.header ×1).

The gain comes from eliminating the Nagle + delayed-ACK stall: without TCP_NODELAY, the server holds small responses for up to 40ms waiting to coalesce a full TCP segment. With 200 sequential request/response pairs this compounds
significantly under any meaningful RTT.

Simulated WAN latency (toxiproxy), 3 runs each

Latency Without TCP_NODELAY With TCP_NODELAY Improvement
50ms ~2230ms ~1840ms ~17%
100ms ~2875ms ~2578ms ~10%

Real network (separate laptop over WiFi, ~9ms RTT), 4 runs each

Build Wallet sync time Improvement
Without TCP_NODELAY (Nagle ON) ~739ms avg (681–817ms)
With TCP_NODELAY ~365ms avg (310–391ms) ~51% faster

The WiFi result is stronger because at 9ms RTT the 40ms Nagle stall represents a larger fraction of each round trip than at 50ms, so it fires more often relative to total time.

Changes

  • src/electrum/server.rs — set TCP_NODELAY on accepted streams before handing off to the connection acceptor
  • src/rest.rs — set TCP_NODELAY on accepted streams before spawning the connection handler; Unix socket path unchanged

  Set TCP_NODELAY on all accepted TCP connections for both the Electrum
  RPC server and the REST HTTP server. Nagle's algorithm interacts poorly
  with TCP delayed ACKs on request/response protocols, adding up to
  200ms of latency per round trip on otherwise idle connections. Unix
  socket path in rest.rs is correctly left unchanged as TCP_NODELAY
  does not apply to Unix domain sockets.
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.

1 participant