Turn Nagle's algorithm off on the web server's connections (#170)
axum 0.7 set TCP_NODELAY on every accepted connection; 0.8 stopped, and serve never set it, so each response sent in parts held its last small segment until the browser's delayed ACK came back. On production's light traffic nothing showed: small responses go out in one write. Under load it did. tests/load, Nagle on then off: media range requests median 41.8 ms to 10.3 ms, p95 44.4 to 13.2, throughput 39 to 149 MB/s. Browse and sign-in unchanged within noise; flag saves vary 80-195 ms either way, behind the scan's writes, not the network. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
10
src/web.rs
10
src/web.rs
@@ -91,9 +91,17 @@ pub fn router(state: WebState) -> Router {
|
||||
}
|
||||
|
||||
pub async fn serve(state: WebState, bind: &str) -> Result<()> {
|
||||
use axum::serve::ListenerExt;
|
||||
// Nagle off, as axum 0.7 had it: under load a response goes out in parts, and with Nagle
|
||||
// on its last small part waits for the browser's delayed ACK, up to 40 ms (#170).
|
||||
let listener = tokio::net::TcpListener::bind(bind)
|
||||
.await
|
||||
.with_context(|| format!("binding {bind}"))?;
|
||||
.with_context(|| format!("binding {bind}"))?
|
||||
.tap_io(|tcp| {
|
||||
if let Err(e) = tcp.set_nodelay(true) {
|
||||
tracing::debug!(error = %e, "could not set TCP_NODELAY");
|
||||
}
|
||||
});
|
||||
tracing::info!(bind, "web ui listening");
|
||||
axum::serve(
|
||||
listener,
|
||||
|
||||
Reference in New Issue
Block a user