Skip to content

WebTransport sendGroup support (and improve sendOrder)#3467

Open
jesup wants to merge 5 commits into
users/jesup/sub_protocolfrom
users/jesup/sendGroup
Open

WebTransport sendGroup support (and improve sendOrder)#3467
jesup wants to merge 5 commits into
users/jesup/sub_protocolfrom
users/jesup/sendGroup

Conversation

@jesup
Copy link
Copy Markdown
Member

@jesup jesup commented Mar 16, 2026

No description provided.

Copilot AI review requested due to automatic review settings March 16, 2026 04:43
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds WebTransport send group support to the QUIC transport and HTTP/3 layers, implementing the spec requirement that WebTransportSendGroups are treated as bandwidth-equals with per-group sendOrder namespacing. The changes introduce a SendGroupId type, per-group scheduling queues with round-robin fairness at the transport layer, and session-scoped send group registration/validation at the HTTP/3 layer.

Changes:

  • New SendGroupId and SendGroup types in neqo-http3, with a global atomic counter for unique IDs and a sentinel value (0) reserved for ungrouped streams.
  • Transport-layer scheduling refactored from flat sendordered/regular queues to per-group PerGroupQueues with round-robin between groups and sendOrder-based priority within each group.
  • HTTP/3 APIs for creating, registering, and validating send groups on WebTransport sessions, including stream creation with send group assignment.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
neqo-http3/src/features/extended_connect/send_group.rs New file: SendGroupId newtype with atomic counter and SendGroup struct
neqo-http3/src/features/extended_connect/mod.rs Adds pub mod send_group
neqo-http3/src/features/extended_connect/webtransport_session.rs Session-level send group registration, validation, and storage
neqo-http3/src/features/extended_connect/webtransport_streams.rs WebTransportSendStream gains send_group field and trait impls
neqo-http3/src/features/extended_connect/session.rs Protocol trait extended with send group methods; forwarding impls
neqo-http3/src/lib.rs Re-exports SendGroupId; adds Stream/SendStream trait methods
neqo-http3/src/connection.rs Http3Connection gains send group set/clear, register/validate, and stream creation with send group
neqo-http3/src/connection_client.rs Public API: webtransport_set_sendgroup, webtransport_register_send_group, webtransport_create_stream_with_send_group
neqo-transport/src/send_stream.rs PerGroupQueues, refactored SendStreams with per_group IndexMap and round-robin scheduling
neqo-transport/src/streams.rs New SendGroupId type alias and set_sendgroup forwarding
neqo-transport/src/connection/mod.rs Public stream_sendgroup API on Connection
neqo-http3/src/features/extended_connect/tests/webtransport/sessions.rs Comprehensive tests for send group creation, validation, cross-session rejection, fair bandwidth allocation, and sendOrder within groups

Comment thread neqo-http3/src/lib.rs Outdated
Comment thread neqo-http3/src/features/extended_connect/webtransport_session.rs
Comment thread neqo-http3/src/features/extended_connect/send_group.rs Outdated
Comment thread neqo-http3/src/connection_client.rs
Comment thread neqo-http3/src/connection.rs
Comment thread neqo-http3/src/connection.rs Outdated
Comment thread neqo-http3/src/features/extended_connect/tests/webtransport/sessions.rs Outdated
Comment thread neqo-http3/src/features/extended_connect/send_group.rs Outdated
Comment thread neqo-http3/src/features/extended_connect/webtransport_session.rs Outdated
Comment thread neqo-transport/src/send_stream.rs Outdated
@jesup jesup changed the title Users/jesup/send group WebTransport sendGroup support (and improve sendOrder) Mar 16, 2026
@jesup jesup force-pushed the users/jesup/sub_protocol branch from c2bb439 to 58be5ff Compare March 17, 2026 18:43
@mxinden
Copy link
Copy Markdown
Member

mxinden commented Apr 1, 2026

Given the large merge conflicts, can you do another rebase before review? Can also review now, though I am afraid comments might get lost.

@larseggert
Copy link
Copy Markdown
Collaborator

It needs a rebase so CI runs

@larseggert larseggert added the needs-rebase PR needs rebasing before it can be merged. label Apr 8, 2026
@jesup jesup force-pushed the users/jesup/sub_protocol branch 2 times, most recently from c140eef to 723a367 Compare April 29, 2026 20:48
@jesup jesup force-pushed the users/jesup/sendGroup branch from 9c15fa5 to 9a89365 Compare April 29, 2026 20:48
@jesup
Copy link
Copy Markdown
Member Author

jesup commented Apr 29, 2026

@jesup jesup force-pushed the users/jesup/sendGroup branch from ad6bc41 to c62d0f9 Compare May 23, 2026 13:37
@larseggert larseggert removed the needs-rebase PR needs rebasing before it can be merged. label May 27, 2026
@jesup jesup force-pushed the users/jesup/sub_protocol branch from a43f069 to 72179ea Compare May 27, 2026 17:41
@jesup jesup force-pushed the users/jesup/sendGroup branch from c62d0f9 to 2a10483 Compare May 27, 2026 17:41
@jesup jesup force-pushed the users/jesup/sub_protocol branch from 72179ea to 8988d8f Compare May 27, 2026 18:27
@jesup jesup force-pushed the users/jesup/sendGroup branch from 2a10483 to df28806 Compare May 27, 2026 18:27
Copy link
Copy Markdown
Collaborator

@larseggert larseggert left a comment

Choose a reason for hiding this comment

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

Lots of new code without test coverage. Tests would benefit from DRY helpers.

Comment thread neqo-http3/src/features/extended_connect/send_group.rs Outdated
Comment thread neqo-http3/src/features/extended_connect/send_group.rs Outdated
Comment thread neqo-http3/src/features/extended_connect/send_group.rs Outdated
Comment thread neqo-http3/src/features/extended_connect/send_group.rs Outdated
Comment thread neqo-transport/src/send_stream.rs Outdated
Comment thread neqo-transport/src/send_stream.rs Outdated
@jesup jesup force-pushed the users/jesup/sub_protocol branch from bef4997 to f05bd91 Compare May 30, 2026 05:42
@jesup jesup force-pushed the users/jesup/sendGroup branch from fc08f9a to f6a6257 Compare May 30, 2026 05:42
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented May 30, 2026

Merging this PR will not alter performance

✅ 23 untouched benchmarks
🗄️ 1 archived benchmark run1


Comparing users/jesup/sendGroup (7166b6a) with users/jesup/sub_protocol (28a5ad3)

Open in CodSpeed

Footnotes

  1. 1 benchmark was run, but is now archived. If it was deleted in another branch, consider rebasing to remove it from the report. Instead if it was added back, click here to restore it.

@jesup jesup force-pushed the users/jesup/sub_protocol branch from f05bd91 to 9430ea7 Compare May 30, 2026 16:57
@jesup jesup force-pushed the users/jesup/sendGroup branch from f6a6257 to 1d61673 Compare May 30, 2026 16:57
@jesup jesup force-pushed the users/jesup/sub_protocol branch from 9430ea7 to 1421dfb Compare June 2, 2026 13:24
@jesup jesup force-pushed the users/jesup/sendGroup branch from 1d61673 to d7f1de8 Compare June 2, 2026 13:24
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 2, 2026

Failed Interop Tests

QUIC Interop Runner, client vs. server, differences relative to users/jesup/sub_protocol at 1421dfb.

neqo-pr as clientneqo-pr as server
neqo-pr vs. go-x-net: BP BA
neqo-pr vs. haproxy: BP BA
neqo-pr vs. kwik: 🚀C1 BP BA
neqo-pr vs. lsquic: run cancelled after 20 min
neqo-pr vs. msquic: A L1 C1
neqo-pr vs. mvfst: A ⚠️BA
neqo-pr vs. neqo: A
neqo-pr vs. nginx: 🚀C1 BP BA
neqo-pr vs. ngtcp2: CM
neqo-pr vs. picoquic: A 🚀BA
neqo-pr vs. quic-go: A
neqo-pr vs. quic-zig: B
neqo-pr vs. quiche: BP BA
neqo-pr vs. s2n-quic: CM
neqo-pr vs. tquic: S BP BA
neqo-pr vs. xquic: A ⚠️L1 C1
aioquic vs. neqo-pr: CM
go-x-net vs. neqo-pr: CM
kwik vs. neqo-pr: BP BA CM
msquic vs. neqo-pr: CM
mvfst vs. neqo-pr: Z A L1 C1 CM
neqo vs. neqo-pr: A
openssl vs. neqo-pr: LR M A CM
quic-go vs. neqo-pr: CM
quiche vs. neqo-pr: 🚀L1 CM
quinn vs. neqo-pr: ⚠️L1 V2 CM
s2n-quic vs. neqo-pr: CM
tquic vs. neqo-pr: CM
xquic vs. neqo-pr: M CM
All results

Succeeded Interop Tests

QUIC Interop Runner, client vs. server

neqo-pr as client

neqo-pr as server

Unsupported Interop Tests

QUIC Interop Runner, client vs. server

neqo-pr as client

neqo-pr as server

@jesup jesup requested a review from larseggert June 2, 2026 19:50
@jesup jesup force-pushed the users/jesup/sub_protocol branch from 1421dfb to d33a540 Compare June 3, 2026 14:36
@jesup jesup force-pushed the users/jesup/sendGroup branch from d7f1de8 to ca788cc Compare June 3, 2026 14:36
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 3, 2026

Benchmark results

Significant performance differences relative to d33a540.

streams/walltime/1000-streams/each-1000-bytes: 💔 Performance has regressed by +2.7023%.
       time:   [37.694 ms 37.733 ms 37.773 ms]
       change: [+2.5430% +2.7023% +2.8562] (p = 0.00 < 0.05)
       Performance has regressed.
Found 6 outliers among 100 measurements (6.00%)
2 (2.00%) low mild
3 (3.00%) high mild
1 (1.00%) high severe
streams-flow-controlled/walltime/1-streams/each-4194304-bytes: 💔 Performance has regressed by +2.5199%.
       time:   [33.753 ms 33.801 ms 33.850 ms]
       change: [+2.2485% +2.5199% +2.7779] (p = 0.00 < 0.05)
       Performance has regressed.
streams-flow-controlled/walltime/10-streams/each-1048576-bytes: 💔 Performance has regressed by +2.0618%.
       time:   [90.167 ms 90.467 ms 90.782 ms]
       change: [+1.4458% +2.0618% +2.6392] (p = 0.00 < 0.05)
       Performance has regressed.
Found 2 outliers among 100 measurements (2.00%)
1 (1.00%) low severe
1 (1.00%) high severe
All results
transfer/1-conn/1-100mb-resp (aka. Download): No change in performance detected.
       time:   [166.88 ms 167.41 ms 168.09 ms]
       thrpt:  [594.92 MiB/s 597.34 MiB/s 599.22 MiB/s]
change:
       time:   [-0.7993% -0.3761% +0.0771] (p = 0.10 > 0.05)
       thrpt:  [-0.0770% +0.3775% +0.8058]
       No change in performance detected.
Found 4 outliers among 100 measurements (4.00%)
1 (1.00%) low mild
2 (2.00%) high mild
1 (1.00%) high severe
transfer/1-conn/10_000-parallel-1b-resp (aka. RPS): Change within noise threshold.
       time:   [268.82 ms 270.99 ms 273.17 ms]
       thrpt:  [36.607 Kelem/s 36.902 Kelem/s 37.199 Kelem/s]
change:
       time:   [+0.3758% +1.4640% +2.5179] (p = 0.01 < 0.05)
       thrpt:  [-2.4560% -1.4429% -0.3744]
       Change within noise threshold.
Found 3 outliers among 100 measurements (3.00%)
3 (3.00%) high mild
transfer/1-conn/1-1b-resp (aka. HPS): No change in performance detected.
       time:   [38.471 ms 38.629 ms 38.810 ms]
       thrpt:  [25.767   B/s 25.887   B/s 25.993   B/s]
change:
       time:   [-0.2791% +0.2663% +0.8698] (p = 0.36 > 0.05)
       thrpt:  [-0.8623% -0.2656% +0.2799]
       No change in performance detected.
Found 6 outliers among 100 measurements (6.00%)
6 (6.00%) high severe
transfer/1-conn/1-100mb-req (aka. Upload): Change within noise threshold.
       time:   [171.14 ms 171.46 ms 171.81 ms]
       thrpt:  [582.05 MiB/s 583.23 MiB/s 584.31 MiB/s]
change:
       time:   [+0.5929% +1.0782% +1.4682] (p = 0.00 < 0.05)
       thrpt:  [-1.4469% -1.0667% -0.5894]
       Change within noise threshold.
Found 3 outliers among 100 measurements (3.00%)
2 (2.00%) high mild
1 (1.00%) high severe
streams/walltime/1-streams/each-1000-bytes: No change in performance detected.
       time:   [566.32 µs 568.35 µs 570.71 µs]
       change: [-0.5849% -0.0562% +0.4861] (p = 0.84 > 0.05)
       No change in performance detected.
Found 10 outliers among 100 measurements (10.00%)
2 (2.00%) high mild
8 (8.00%) high severe
streams/walltime/1000-streams/each-1-bytes: Change within noise threshold.
       time:   [11.581 ms 11.602 ms 11.625 ms]
       change: [-1.0766% -0.5368% -0.1422] (p = 0.01 < 0.05)
       Change within noise threshold.
Found 3 outliers among 100 measurements (3.00%)
3 (3.00%) high mild
streams/walltime/1000-streams/each-1000-bytes: 💔 Performance has regressed by +2.7023%.
       time:   [37.694 ms 37.733 ms 37.773 ms]
       change: [+2.5430% +2.7023% +2.8562] (p = 0.00 < 0.05)
       Performance has regressed.
Found 6 outliers among 100 measurements (6.00%)
2 (2.00%) low mild
3 (3.00%) high mild
1 (1.00%) high severe
streams-flow-controlled/walltime/1-streams/each-4194304-bytes: 💔 Performance has regressed by +2.5199%.
       time:   [33.753 ms 33.801 ms 33.850 ms]
       change: [+2.2485% +2.5199% +2.7779] (p = 0.00 < 0.05)
       Performance has regressed.
streams-flow-controlled/walltime/10-streams/each-1048576-bytes: 💔 Performance has regressed by +2.0618%.
       time:   [90.167 ms 90.467 ms 90.782 ms]
       change: [+1.4458% +2.0618% +2.6392] (p = 0.00 < 0.05)
       Performance has regressed.
Found 2 outliers among 100 measurements (2.00%)
1 (1.00%) low severe
1 (1.00%) high severe
transfer/walltime/pacing-false/varying-seeds: Change within noise threshold.
       time:   [19.028 ms 19.052 ms 19.085 ms]
       change: [-1.5707% -1.3738% -1.1746] (p = 0.00 < 0.05)
       Change within noise threshold.
Found 5 outliers among 100 measurements (5.00%)
1 (1.00%) low mild
3 (3.00%) high mild
1 (1.00%) high severe
transfer/walltime/pacing-true/varying-seeds: Change within noise threshold.
       time:   [19.666 ms 19.682 ms 19.698 ms]
       change: [-0.7779% -0.6371% -0.5125] (p = 0.00 < 0.05)
       Change within noise threshold.
Found 1 outliers among 100 measurements (1.00%)
1 (1.00%) high mild
transfer/walltime/pacing-false/same-seed: Change within noise threshold.
       time:   [19.149 ms 19.164 ms 19.181 ms]
       change: [-0.5857% -0.3587% -0.1835] (p = 0.00 < 0.05)
       Change within noise threshold.
Found 4 outliers among 100 measurements (4.00%)
2 (2.00%) low mild
1 (1.00%) high mild
1 (1.00%) high severe
transfer/walltime/pacing-true/same-seed: Change within noise threshold.
       time:   [19.574 ms 19.596 ms 19.619 ms]
       change: [-2.5563% -2.3622% -2.1924] (p = 0.00 < 0.05)
       Change within noise threshold.
Found 2 outliers among 100 measurements (2.00%)
1 (1.00%) high mild
1 (1.00%) high severe

Download data for profiler.firefox.com or download performance comparison data.

@jesup jesup dismissed larseggert’s stale review June 3, 2026 21:17

I can't find any items needing resolution; will dismiss and request re-review

@jesup jesup force-pushed the users/jesup/sub_protocol branch from d33a540 to 31eb305 Compare June 3, 2026 21:24
@jesup jesup force-pushed the users/jesup/sendGroup branch from ca788cc to 53b10d4 Compare June 3, 2026 21:24
jesup added 5 commits June 4, 2026 10:35
Fixes existing bug where low priority streams could be starved forever:
  After the highest-sendOrder stream within a group exhausted its queued data (but remained open),
  PerGroupQueues::next_stream_id() kept returning it, permanently starving lower-sendOrder streams
  in the same group.
@jesup jesup force-pushed the users/jesup/sub_protocol branch from 31eb305 to 28a5ad3 Compare June 4, 2026 14:36
@jesup jesup force-pushed the users/jesup/sendGroup branch from 53b10d4 to 7166b6a Compare June 4, 2026 14:36
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 4, 2026

Client/server transfer results

Performance differences relative to 28a5ad3.

Transfer of 33554432 bytes over loopback, min. 100 runs. All unit-less numbers are in milliseconds.

Client vs. server (params) Mean ± σ Min Max MiB/s ± σ Δ baseline Δ baseline
neqo-msquic-cubic 146.3 ± 1.5 143.7 152.9 218.7 ± 21.3 💔 0.4 0.3%
quiche-neqo-cubic 183.0 ± 2.8 173.9 191.1 174.9 ± 11.4 💚 -1.6 -0.8%

Table above only shows statistically significant changes. See all results below.

All results

Transfer of 33554432 bytes over loopback, min. 100 runs. All unit-less numbers are in milliseconds.

Client vs. server (params) Mean ± σ Min Max MiB/s ± σ Δ baseline Δ baseline
google-google-nopacing 458.3 ± 1.7 453.3 465.0 69.8 ± 18.8
google-neqo-cubic 265.3 ± 2.5 258.9 271.2 120.6 ± 12.8 0.3 0.1%
msquic-msquic-nopacing 145.2 ± 48.8 112.0 343.5 220.3 ± 0.7
msquic-neqo-cubic 175.5 ± 77.1 118.5 530.7 182.4 ± 0.4 -2.6 -1.5%
neqo-google-cubic 768.5 ± 2.3 762.5 775.3 41.6 ± 13.9 -0.4 -0.1%
neqo-msquic-cubic 146.3 ± 1.5 143.7 152.9 218.7 ± 21.3 💔 0.4 0.3%
neqo-neqo-cubic 81.1 ± 2.6 75.6 87.3 394.8 ± 12.3 -0.5 -0.6%
neqo-neqo-cubic-nopacing 81.0 ± 2.9 76.2 90.1 395.3 ± 11.0 0.6 0.7%
neqo-neqo-newreno 81.0 ± 2.7 75.8 88.9 394.9 ± 11.9 -0.4 -0.4%
neqo-neqo-newreno-nopacing 80.8 ± 2.9 74.1 88.3 395.9 ± 11.0 0.7 0.8%
neqo-quiche-cubic 192.5 ± 2.5 188.6 201.7 166.2 ± 12.8 0.5 0.3%
neqo-s2n-cubic 215.1 ± 1.7 209.8 221.2 148.7 ± 18.8 -0.6 -0.3%
quiche-neqo-cubic 183.0 ± 2.8 173.9 191.1 174.9 ± 11.4 💚 -1.6 -0.8%
quiche-quiche-nopacing 138.4 ± 3.0 133.6 151.2 231.2 ± 10.7
s2n-neqo-cubic 216.7 ± 4.3 207.6 228.3 147.7 ± 7.4 0.8 0.4%
s2n-s2n-nopacing 292.6 ± 25.9 280.3 391.8 109.4 ± 1.2

Download data for profiler.firefox.com or download performance comparison data.

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.

4 participants