From ee106d936ef3ae2fe93e5113970ad1415d64fda4 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Mon, 9 Nov 2026 00:22:21 -0800 Subject: [PATCH 1/3] chore(quest): claim quest/m0/nightly/session-bench-handshake.md Quest-Claim: 1deece756db43826 From 2f214d407155ca5cb6904033abc4ffc89afc3309 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Mon, 9 Nov 2026 04:41:08 -0800 Subject: [PATCH 2/3] fix(net): the session bench gives each cell its own runtime and a proxying relay The session bench shared one current-thread runtime across a group's cells, so the sessions a dropped room left behind ran their teardown inside the next cell's setup. After moq-lite-07 at 4096 broadcasts that work took longer than the server's 10s handshake deadline, so moq-transport-22 at 16 broadcasts failed with Timeout. Each cell now gets its own runtime. The model relay also proxies again: #8266 dropped the harness's proxy flag, so moq-lite-07 viewers never learned the publisher's routes and hung. Co-Authored-By: Claude Opus 5.5 --- quest/m0/nightly/README.md | 1 - quest/m0/nightly/session-bench-handshake.md | 19 ------------------- rs/moq-net/benches/session/mod.rs | 19 ++++++++++++------- 3 files changed, 12 insertions(+), 27 deletions(-) delete mode 100644 quest/m0/nightly/session-bench-handshake.md diff --git a/quest/m0/nightly/README.md b/quest/m0/nightly/README.md index 3a82a9d0589..9019d7c81b0 100644 --- a/quest/m0/nightly/README.md +++ b/quest/m0/nightly/README.md @@ -52,6 +52,5 @@ near the paired threshold (re-check if one repeats), a one-off - [Nightly's macOS platform job passes](/quest/m0/nightly/macos.md) - `moq-audio`'s tests compile on macOS again and the websocket version test's timeout is fixed if it recurs - [The qmux startup benchmark's fake peer sends transport parameters](/quest/m0/nightly/qmux-bench-peer.md) - Audio quality's WebSocket startup step stops timing out -- [The moq-net session bench completes moq-transport-22 at 16 broadcasts](/quest/m0/nightly/session-bench-handshake.md) - the bench workload stops panicking on a handshake timeout - [Bisect the moq-audio bus and moq-mux parameter_sets regressions](/quest/m0/nightly/bench-regressions.md) - two real benchmark regressions are explained and fixed or accepted - [Moxygen conformance cells pass again](/quest/m0/nightly/moxygen-conformance.md) - the first-object signal and integer extensions survive, or moxygen's divergence is skipped with an upstream link diff --git a/quest/m0/nightly/session-bench-handshake.md b/quest/m0/nightly/session-bench-handshake.md deleted file mode 100644 index 2601a6e630e..00000000000 --- a/quest/m0/nightly/session-bench-handshake.md +++ /dev/null @@ -1,19 +0,0 @@ -# [S] The moq-net session bench completes moq-transport-22 at 16 broadcasts - -## Goal - -Nightly's "Rust bench targets" workload runs `moq-net`'s session bench to the -end: `session_delivery_broadcasts/moq-transport-22/.../broadcasts=16` no -longer panics with `server handshake failed: Timeout` -(`harness.rs:233`). - -## Plan - -Planned 2026-11-09 (maintainer, /quest-complete from the triage of Nightly -run [42487375545](https://github.com/moq-dev/moq/actions/runs/42487375545), -where it first failed this way). Reproduce it first, then fix the cause: -a handshake that stalls under that load is a bug in the session or the -harness, never a reason to raise the timeout. Check whether the harness -reuses state across cells and whether lite versions pass the same cell. - -Public API: none expected. Wire: none. diff --git a/rs/moq-net/benches/session/mod.rs b/rs/moq-net/benches/session/mod.rs index d943ef5d156..67141f086bb 100644 --- a/rs/moq-net/benches/session/mod.rs +++ b/rs/moq-net/benches/session/mod.rs @@ -417,6 +417,8 @@ impl Instructions { } } +/// A current-thread runtime for one benchmark cell: the sessions a cell leaves behind stop +/// with its runtime instead of running inside the next cell's setup and samples. fn runtime() -> tokio::runtime::Runtime { tokio::runtime::Builder::new_current_thread() .enable_time() @@ -531,7 +533,10 @@ impl Backend for Model { const PREFIX: &'static str = ""; fn relay(id: u64, capacity: Option) -> (Self::Relay, cache::Pool) { - make_origin(id, capacity) + // A relay forwards the routes it learns, as moq-relay's cluster does; off, a + // moq-lite-07 viewer never learns the publisher's broadcasts. + let (origin, pool) = make_origin(id, capacity); + (origin.with_proxy(true), pool) } fn origin(relay: &Self::Relay) -> &origin::Producer { @@ -1190,7 +1195,6 @@ impl Room { } fn delivery(c: &mut Criterion, name: &str, shapes: impl IntoIterator) { - let rt = runtime(); let shapes: Vec<_> = shapes.into_iter().collect(); let cpu = if std::env::var_os("SESSION_CPU").is_some() { "_cpu" @@ -1200,6 +1204,7 @@ fn delivery(c: &mut Criterion, name: &str, shapes: impl IntoIterator let mut group = c.benchmark_group(format!("{}session_delivery_{name}{cpu}", B::PREFIX)); for version in VERSIONS { for shape in shapes.iter().filter(|shape| shape.runs_on(version)) { + let rt = runtime(); // Built on first call: Criterion only calls a routine its filter // selects, and calls it again for every sample. let mut room = None; @@ -1309,11 +1314,11 @@ pub(crate) fn range_updates(c: &mut Criterion) { if std::env::var_os("SESSION_ALLOCS").is_some() || std::env::var_os("SESSION_EXPIRY_ONLY").is_some() { return; } - let rt = runtime(); let mut group = c.benchmark_group(format!("{}session_range_updates", B::PREFIX)); group.sample_size(10); for span in [2u64, 16] { for requests in [1usize, 16] { + let rt = runtime(); group.throughput(Throughput::Elements(requests as u64)); group.bench_function(BenchmarkId::new(format!("groups_{span}"), requests), |b| { let (mut cluster, mut viewers) = rt.block_on(async { @@ -1407,11 +1412,11 @@ pub(crate) fn range_updates(c: &mut Criterion) { } fn join(c: &mut Criterion, name: &str, shapes: impl IntoIterator) { - let rt = runtime(); let shapes: Vec<_> = shapes.into_iter().collect(); let mut group = c.benchmark_group(format!("{}session_join_{name}", B::PREFIX)); for version in VERSIONS { for shape in &shapes { + let rt = runtime(); let mut cluster = None; group.bench_function(BenchmarkId::from_parameter(shape.id(version)), |b| { let cluster = cluster.get_or_insert_with(|| { @@ -1573,12 +1578,12 @@ impl DashRoom { } fn dash(c: &mut Criterion, name: &str, shapes: impl IntoIterator) { - let rt = runtime(); let shapes: Vec<_> = shapes.into_iter().collect(); let mut group = c.benchmark_group(format!("{}session_dash_{name}", B::PREFIX)); group.sample_size(10); for version in DASH_VERSIONS { for shape in &shapes { + let rt = runtime(); let mut room = None; group.throughput(Throughput::Elements(shape.total() as u64)); group.bench_function(BenchmarkId::from_parameter(shape.id(version)), |b| { @@ -1597,7 +1602,6 @@ fn allocations() { println!("group::Consumer: {} bytes", size_of::()); - let rt = runtime(); let fanout = Shape { publishers: 1, viewers: 256, @@ -1609,6 +1613,7 @@ fn allocations() { let shapes: Vec<_> = groups.chain(datagram_shapes()).collect(); for version in VERSIONS { for &shape in shapes.iter().filter(|shape| shape.runs_on(version)) { + let rt = runtime(); let mut room = rt.block_on(Room::::new(version, shape)); room.instructions = Instructions::open(); ALLOCATIONS.store(0, Ordering::Relaxed); @@ -1752,12 +1757,12 @@ impl ChurnRoom { } fn churn(c: &mut Criterion, name: &str, shapes: impl IntoIterator) { - let rt = runtime(); let shapes: Vec<_> = shapes.into_iter().collect(); let mut group = c.benchmark_group(format!("{}session_churn_{name}", B::PREFIX)); group.throughput(Throughput::Elements(1)); for version in CHURN_VERSIONS { for shape in &shapes { + let rt = runtime(); let mut room = None; group.bench_function(BenchmarkId::from_parameter(shape.id(version)), |b| { let room = room.get_or_insert_with(|| rt.block_on(ChurnRoom::::new(version, *shape))); From cf5c44dd057c478941acb78a4580724d9adcdf71 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Mon, 9 Nov 2026 04:46:05 -0800 Subject: [PATCH 3/3] fix(net): fanout_threads gives each cell its own runtime too Co-Authored-By: Claude Opus 5.5 --- rs/moq-net/benches/session/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rs/moq-net/benches/session/mod.rs b/rs/moq-net/benches/session/mod.rs index 67141f086bb..0604fa90ea7 100644 --- a/rs/moq-net/benches/session/mod.rs +++ b/rs/moq-net/benches/session/mod.rs @@ -1837,8 +1837,8 @@ pub(crate) fn fanout_threads(c: &mut Criterion) { // Groups delivered per round: one to each viewer. group.throughput(Throughput::Elements(shape.viewers as u64)); for workers in [1, 16] { - let rt = threaded(workers); for version in ["moq-lite-06", "moq-lite-07-wip"] { + let rt = threaded(workers); let mut room = None; group.bench_function(format!("{version}/workers={workers}"), |b| { let room = room.get_or_insert_with(|| {