Skip to content

bench(net): sweep equal-cost pool resolution and churn - #4607

Merged
kixelated merged 3 commits into
quest/m0/wildcard/READMEfrom
quest/m0/wildcard/pool-bench
Sep 30, 2026
Merged

kixelated merged 3 commits into
quest/m0/wildcard/READMEfrom
quest/m0/wildcard/pool-bench

Conversation

@kixelated

Copy link
Copy Markdown
Collaborator

Completes quest/m0/wildcard/pool-bench.md, a child of the wildcard line (#4403).

Problem

#4279 keyed route_order's tie-break on the requested path, so resolving a path scans the equal-cost pool and hashes the path with every member's hops. Only a correctness test covered it; AGENTS.md asks for a two-axis sweep for anything that fans out.

Approach

Two groups in rs/moq-net/benches/origin.rs, each swept over pool members (4, 32, 256) x paths the pool already serves (100, 1k, 10k):

  • origin/pool_resolve: one new path resolved through the public API, from request_broadcast to the chosen member holding the request. The member refuses it untimed so every iteration mints a fresh front.
  • origin/pool_churn: one member joining then leaving the pool. Every front under the prefix re-selects on both changes, so this is paths x members by design. An untimed check asserts no front moves to the newcomer.

Both are compiled by the PR gate (clippy --all-targets) and run once by the nightly moq-net benchmark smoke.

Results

About 15 agents shared a 32-core machine (load average ~50) while these ran, so absolute numbers are noisy by up to 2x between runs. Read the slopes, not the values.

pool_resolve (per request):

members 100 paths 1k paths 10k paths
4 4.6 µs 7.9 µs 5.0 µs
32 6.8 µs 7.7 µs 15 µs
256 40 µs 42 µs 96 µs
  • Members: linear, about 140 ns per member per resolution (two pool scans: the request's best_route check and the front's selection). Irrelevant at realistic pool sizes, and paid once per front, not per subscriber.
  • Paths: no algorithmic dependence I could find (the watch lives on the path's own node, and WeakCache GCs ended fronts). The 10k column's rise is cache pressure plus noise; reruns of 256m gave 58/102/104 µs.

pool_churn (per join + leave):

members 100 paths 1k paths 10k paths
4 0.22 ms 19 ms 223 ms
32 0.66 ms 18 ms 289 ms
256 4.5 ms 118 ms 586 ms
  • Paths: linear at scale, roughly 10 µs per served path per change once the fronts fall out of cache (a finer 100..3200 sweep showed ~1 µs per path while they fit, rising to 6 to 9 µs). About 1 µs of that is the synchronous announce poking each path's watch; the rest is each front task re-selecting in the driver.
  • Members: about 70 ns per member per path per change, the same scan as resolution.

This matters: a single worker joining or leaving a pool that serves 10k paths costs a relay's origin driver 100 to 300 ms of single-threaded work, even though no front can switch to the newcomer (a pinned front only accepts its own publisher). Not optimized here per the quest; proposed as a follow-up below.

Impact

  • None. Bench-only; no public API or wire change.

Alternatives

  • Calling the private best_route directly (as the unit test does) would isolate the scan, but a bench cannot reach it without exporting it, and the public path is what a relay pays.
  • Sweeping tracks per front for the driver's per-event admission walk (the other gap feat(net): spread a prefix's pool across paths, stitch on the reply's origin #4279 listed): not cheap. Front::admit only returns an origin once a lite-07 copy's reply names one, so it needs mock sessions (the session bench harness), and the session round trip would swamp the O(tracks) walk at small counts. Left as a follow-up.

Follow-ups

  • Pool churn wakes every front under the prefix: a membership change could poke only fronts whose pin the changed route can qualify for (or a pinned front could skip re-selection when the change cannot affect it).
  • Tracks-per-front sweep for the admission walk in run_front, over lite-07 mock sessions.

Checks

just check passes. cargo bench -p moq-net --bench origin -- pool --test passes.

🤖 Generated with Claude Code

(Written by Claude Opus 5.5)

kixelated and others added 3 commits September 30, 2026 09:33
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds origin/pool_resolve and origin/pool_churn, each swept over pool
members against the paths the pool already serves, and completes the
pool-bench quest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated

Copy link
Copy Markdown
Collaborator Author

Outcome: both sweeps landed, just check passes, and the PR stays a draft for maintainer review.

Open decisions:

  • Pool churn costs O(paths x members) of driver time per membership change, about 0.1 to 0.3 s at 10k served paths. Recommendation: plan a follow-up quest that pokes only the fronts a changed route can qualify for, instead of optimizing here.
  • The tracks-per-front admission-walk sweep was skipped because it needs lite-07 mock sessions. Recommendation: make it its own small quest on the session bench.

(Written by Claude Opus 5.5)

@kixelated

Copy link
Copy Markdown
Collaborator Author

Decision: this PR goes ahead as the benchmark only. The pool churn fix (waking only the fronts a route change can affect) will be planned as a separate quest and stays out of this PR. Marking ready for review.

(Written by Claude Opus 5.5)

@kixelated
kixelated marked this pull request as ready for review September 30, 2026 18:01
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-30T18:05:26.212937Z bf70b23 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@kixelated kixelated left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review by review (OpenAI)
(Written by OpenAI)

Reviewed moq-dev/moq at bf70b23108fc4ca85dea80285ca906723160b549.

No actionable bugs found. The public-API resolution sweep keeps existing fronts alive and retires each refused probe outside timing (origin.rs:435-477); the churn sweep drives join and leave separately and checks that pinned fronts do not migrate (489-514). Pool size and served-path count vary independently, and the existing nightly all-bench smoke includes these routines.

Direction: keep this benchmark-only. Measuring the public path avoids exporting private routing internals, and separating the churn optimization preserves a useful baseline without extra production complexity. No API or wire change.

Limits: source review only; I did not run benchmarks or tests, or independently reproduce the reported timings. Nightly smoke checks execution, not performance thresholds.

@kixelated
kixelated merged commit 077df1f into quest/m0/wildcard/README Sep 30, 2026
7 checks passed
@kixelated
kixelated deleted the quest/m0/wildcard/pool-bench branch September 30, 2026 18:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant