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,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Cover art up to 20 MB is shown, instead of nothing for anything over 5 MB, as for five of the Glass Cannon Network's feeds.
|
- Cover art up to 20 MB is shown, instead of nothing for anything over 5 MB, as for five of the Glass Cannon Network's feeds.
|
||||||
|
- Seeking in an episode while many people listen answers in about 10 ms instead of 40, and files stream about four times as fast: each connection now sends what is ready without waiting for the browser to acknowledge the last part.
|
||||||
- Artwork that could not be fetched is not fetched again for an hour, instead of on every page load, and the server's log says which image it was and why.
|
- Artwork that could not be fetched is not fetched again for an hour, instead of on every page load, and the server's log says which image it was and why.
|
||||||
|
|
||||||
## [0.10.3] - 2026-10-09
|
## [0.10.3] - 2026-10-09
|
||||||
|
|||||||
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<()> {
|
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)
|
let listener = tokio::net::TcpListener::bind(bind)
|
||||||
.await
|
.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");
|
tracing::info!(bind, "web ui listening");
|
||||||
axum::serve(
|
axum::serve(
|
||||||
listener,
|
listener,
|
||||||
|
|||||||
Reference in New Issue
Block a user