Skip to content

Commit ef9957b

Browse files
kixelatedclaude
andcommitted
proto: lazily allocate remote stream slots
`StreamsState::new` used to eagerly insert `(id, None)` placeholder entries in both `send` and `recv` FxHashMaps for every remote stream id in `0..max_remote[dir]`. With `max_concurrent_*_streams = 10_000` (e.g. for MoQ relay nodes that burn through short-lived streams), hashbrown rounded each map's bucket array up to ~65K buckets, costing ~0.5-2 MB of bucket memory per Connection before any stream data was sent. Move that work into a lazy frontier-advance step at the top of each remote receive path. Remote stream state: - `id.index() >= max_remote[dir]`: not allowed - `id.index() >= next_remote[dir]`: allowed, absent from map - `id.index() < next_remote[dir]`, present: active - `id.index() < next_remote[dir]`, absent: closed RFC 9000 section 3.2 says receiving a frame for index N implicitly opens all lower indices. `ensure_remote` handles that by materializing `None` placeholders for every index in `[next_remote, id.index()]` - otherwise a late out-of-order frame for a skipped index would land on "absent from map" and get dropped as closed. Placeholders are short-lived: they get filled on first real access or removed when the stream closes, so unlike a growing "closed ids" set the map stays bounded by currently live streams even across heavy churn. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent dc86400 commit ef9957b

3 files changed

Lines changed: 244 additions & 51 deletions

File tree

quinn-proto/src/connection/streams/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ impl<'a> Streams<'a> {
5555

5656
self.state.next[dir as usize] += 1;
5757
let id = StreamId::new(self.state.side, dir, self.state.next[dir as usize] - 1);
58-
self.state.insert(false, id);
58+
self.state.insert_local(id);
5959
self.state.send_streams += 1;
6060
Some(id)
6161
}

0 commit comments

Comments
 (0)