From 8efb8a002d5af27d6466092d41b8992befc94486 Mon Sep 17 00:00:00 2001 From: Lann Martin Date: Mon, 10 Aug 2026 20:34:37 -0400 Subject: [PATCH] rust/wasmtime: set TCP_NODELAY on the connected socket MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Latency-sensitive guests (QUIC over the message stream, per component-iroh) write small messages back-to-back; Nagle holds the second write until the peer's delayed ACK arrives, a ~40 ms stall per occurrence on Linux loopback. Browsers run WebSocket sockets with TCP_NODELAY, so the wasmtime host was the deficient implementation on the portability ladder (enhance, never accumulate divergence). Found driving component-iroh's endpoint to event-driven wakeups (polymorph-components/component-iroh#42): with flushes no longer batched by a 10 ms clock tick, back-to-back small sends surfaced the stall — relay-wire echo roundtrips sat at 27-50 ms and drop to 0-7 ms with this change. Verified: just check; just conformance-ct (4 targets, 220 results, 0 failing). --- rust/wasmtime/src/websocket.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/rust/wasmtime/src/websocket.rs b/rust/wasmtime/src/websocket.rs index f591a86..1a48d47 100644 --- a/rust/wasmtime/src/websocket.rs +++ b/rust/wasmtime/src/websocket.rs @@ -480,6 +480,21 @@ impl Websocket { } }; + // Latency-sensitive guests (QUIC over the message stream) write + // small messages back-to-back; Nagle would hold the second until + // the peer's delayed ACK. Browsers run WebSocket sockets with + // TCP_NODELAY; match them. + { + let tcp = match ws.get_ref() { + tokio_tungstenite::MaybeTlsStream::Plain(tcp) => Some(tcp), + tokio_tungstenite::MaybeTlsStream::Rustls(tls) => Some(tls.get_ref().0), + _ => None, + }; + if let Some(tcp) = tcp { + let _ = tcp.set_nodelay(true); + } + } + let negotiated = response .headers() .get("Sec-WebSocket-Protocol")