From 014e24f7717f0aa47507b5fcfbd2bdfd4d7689a2 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Fri, 11 Sep 2026 01:01:12 +0200 Subject: [PATCH] Size the media receive buffer like the producer's send buffer A 12 Mbps stream is about 2,300 datagrams a second; the OS default receive buffer holds a few milliseconds of it, and every poll gap longer than that is loss on a wire that lost nothing. Co-Authored-By: Claude Fable 5.1 --- Cargo.lock | 1 + crates/ratatoskr-core/Cargo.toml | 1 + crates/ratatoskr-core/src/receiver.rs | 10 ++++++++++ 3 files changed, 12 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 9ec91f9..dd40e5b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -615,6 +615,7 @@ dependencies = [ "cultmesh-rs", "cultnet-rs", "rmp-serde", + "socket2", ] [[package]] diff --git a/crates/ratatoskr-core/Cargo.toml b/crates/ratatoskr-core/Cargo.toml index 9b544dd..a5d75c6 100644 --- a/crates/ratatoskr-core/Cargo.toml +++ b/crates/ratatoskr-core/Cargo.toml @@ -16,6 +16,7 @@ chrono = "0.4" cultnet-rs = { git = "https://github.com/GameCult/CultLib.git", rev = "c84cb2e", package = "cultnet-rs" } cultmesh-rs = { git = "https://github.com/GameCult/CultLib.git", rev = "c84cb2e", package = "cultmesh-rs" } cultcache-rs = { git = "https://github.com/GameCult/CultLib.git", rev = "c84cb2e", package = "cultcache-rs" } +socket2 = "0.5" [dev-dependencies] rmp-serde = "1.3" diff --git a/crates/ratatoskr-core/src/receiver.rs b/crates/ratatoskr-core/src/receiver.rs index e7105c6..3923d9d 100644 --- a/crates/ratatoskr-core/src/receiver.rs +++ b/crates/ratatoskr-core/src/receiver.rs @@ -30,6 +30,10 @@ use crate::video::{ExpiredFrame, VideoAssembler, VideoAssemblerOptions, VideoFra /// takes it as a parameter so no consumer's name is baked into the contract. pub const RATATOSKR_MEDIA_PRODUCER: &str = "ratatoskr"; +/// Kernel receive buffer for the media socket. Matches the producer's send +/// buffer; the OS default is a few milliseconds of a 12 Mbps stream. +const RECEIVE_BUFFER_BYTES: usize = 16 * 1024 * 1024; + #[derive(Clone, Debug)] pub struct ReceiverOptions { /// The producer's advertised media endpoint, to dial. @@ -402,6 +406,12 @@ impl RatatoskrReceiver { fn dial(producer: SocketAddr, runtime_id: &str, connection_id: u32) -> Result { let bind = if producer.is_ipv4() { "0.0.0.0:0" } else { "[::]:0" }; let socket = UdpSocket::bind(bind).with_context(|| format!("binding a socket to dial {producer}"))?; + // A 12 Mbps stream is ~2,300 datagrams a second; the OS default receive + // buffer holds a few milliseconds of that, and every poll gap longer than + // it is loss on a wire that lost nothing. Sized like the producer's. + socket2::SockRef::from(&socket) + .set_recv_buffer_size(RECEIVE_BUFFER_BYTES) + .context("sizing the Ratatoskr media receive buffer")?; socket .set_nonblocking(true) .context("setting the Ratatoskr media socket nonblocking")?;