Repository navigation
WebTransport: report the fate of outgoing datagrams via aggregate stats - #4091
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4091 +/- ##
==========================================
- Coverage 97.13% 96.99% -0.14%
==========================================
Files 113 118 +5
Lines 41524 41887 +363
Branches 41524 41887 +363
==========================================
+ Hits 40334 40629 +295
- Misses 1176 1234 +58
- Partials 14 24 +10
Flags with carried forward coverage won't be shown. Click here to find out more.
|
There was a problem hiding this comment.
🟡 Changes recommended
Idle server connections can leave sent and dropped datagram statistics stale because pending counters do not trigger HTTP/3 processing.
1 open issue
What changed in this PR
Adds aggregate outgoing WebTransport datagram statistics alongside expiry counts.
Changes:
- Tracks sent and dropped datagrams per session.
- Includes queued datagram outcomes in close-time statistics.
- Adds accounting and pending-counter tests.
| File | Description |
|---|---|
| neqo-transport/src/quic_datagrams.rs | Detects all pending outcome counters. |
| neqo-transport/src/datagram_queue.rs | Adds pending-counter predicate. |
| neqo-transport/src/connection/tests/datagram.rs | Tests pending sent counts. |
| neqo-transport/src/connection/mod.rs | Updates counter API documentation. |
| neqo-http3/src/webtransport.rs | Reads statistics after closing. |
| neqo-http3/src/features/extended_connect/webtransport_session.rs | Records sent and dropped totals. |
| neqo-http3/src/features/extended_connect/tests/webtransport/datagrams.rs | Tests aggregate outcome accounting. |
| neqo-http3/src/features/extended_connect/stats.rs | Exposes sent and dropped fields. |
| neqo-http3/src/features/extended_connect/session.rs | Collects queue and capsule outcomes. |
| neqo-http3/src/connection.rs | Drains counters and preserves closed-session access. |
| neqo-http3/src/connect_udp.rs | Adapts to the close helper’s return value. |
Review effort: Balanced
Merging this PR will regress 1 benchmark
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ❌ | Simulation | decode 10 STREAM frames |
3.8 µs | 3.9 µs | -2.74% |
| ⚡ | WallTime | 1-conn/1-100mb-resp (aka. Download) |
49.8 ms | 47.7 ms | +4.41% |
| ⚡ | WallTime | quiche-neqo |
44.5 ms | 43.1 ms | +3.08% |
| ⚡ | WallTime | s2n-neqo |
128.4 ms | 125.4 ms | +2.34% |
Tip
Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.
Comparing users/jesup/report_datagrams (fb2f47c) with main (d245301)
62589ab to
6325866
Compare
|
This PR is part of a stack of 4 bookmarks:
Created with jj-stack |
Adds SessionStats::datagrams_sent_outgoing/datagrams_dropped_outgoing, backed by the per-session sent count from the previous commit, so that once a session's queue is empty, every datagram a caller handed in has been counted as sent, expired or dropped exactly once. Dropped covers byte-budget evictions, datagrams refused at enqueue as the lowest priority, datagrams dropped at packet-build time as too big for the path MTU, and datagrams still queued when the session closes. The Capsule fallback counts as sent on write. close_session flushes the sent count and drops what is still queued before snapshotting the stats it returns, so the final values include the datagrams that call discards; a close or reset from the peer drops and counts the queue too. Both close paths expire stale datagrams first, so those count as expired rather than dropped. The per-tick sweep only visits the sessions the transport reports as having work.
6325866 to
fb2f47c
Compare
Failed Interop TestsQUIC Interop Runner, client vs. server, differences relative to
All resultsSucceeded Interop TestsQUIC Interop Runner, client vs. server neqo-pr as client
neqo-pr as server
Unsupported Interop TestsQUIC Interop Runner, client vs. server neqo-pr as client
neqo-pr as server
|
Benchmark resultsNo significant performance differences relative to d245301. All resultstransfer/1-conn/1-100mb-req (aka. Upload)/mtu-1500 time: [51.107 ms 51.138 ms 51.170 ms]
thrpt: [1.9085 GiB/s 1.9097 GiB/s 1.9108 GiB/s]
Found 3 outliers among 100 measurements (3.00%)
3 (3.00%) high mildtransfer/1-conn/1-100mb-resp (aka. Download)/mtu-1500 time: [51.037 ms 51.073 ms 51.110 ms]
thrpt: [1.9107 GiB/s 1.9121 GiB/s 1.9134 GiB/s]
Found 3 outliers among 100 measurements (3.00%)
3 (3.00%) high mildtransfer/1-conn/1-1b-resp (aka. HPS)/mtu-1500 time: [2.9129 ms 2.9138 ms 2.9147 ms]
thrpt: [343.09 B/s 343.20 B/s 343.30 B/s]
Found 3 outliers among 100 measurements (3.00%)
1 (1.00%) low mild
1 (1.00%) high mild
1 (1.00%) high severetransfer/1-conn/10_000-parallel-1b-resp (aka. RPS)/mtu-1500 time: [66.594 ms 66.929 ms 67.266 ms]
thrpt: [148.66 Kelem/s 149.41 Kelem/s 150.16 Kelem/s]
Found 2 outliers among 100 measurements (2.00%)
1 (1.00%) low mild
1 (1.00%) high mildstreams-flow-controlled/walltime/1-streams/each-4194304-bytes time: [10.709 ms 10.713 ms 10.716 ms]
thrpt: [373.26 MiB/s 373.39 MiB/s 373.52 MiB/s]
Found 3 outliers among 100 measurements (3.00%)
2 (2.00%) low mild
1 (1.00%) high mildstreams-flow-controlled/walltime/10-streams/each-1048576-bytes time: [28.671 ms 28.684 ms 28.698 ms]
thrpt: [348.46 MiB/s 348.62 MiB/s 348.78 MiB/s]
Found 3 outliers among 100 measurements (3.00%)
3 (3.00%) high mildstreams/walltime/1-streams/each-1000-bytes time: [131.10 µs 131.63 µs 132.30 µs]
thrpt: [7.2086 MiB/s 7.2452 MiB/s 7.2743 MiB/s]
Found 2 outliers among 100 measurements (2.00%)
1 (1.00%) high mild
1 (1.00%) high severestreams/walltime/1000-streams/each-1-bytes time: [3.9134 ms 3.9252 ms 3.9363 ms]
thrpt: [248.09 KiB/s 248.79 KiB/s 249.54 KiB/s]streams/walltime/1000-streams/each-1000-bytes time: [12.580 ms 12.590 ms 12.600 ms]
thrpt: [75.689 MiB/s 75.748 MiB/s 75.810 MiB/s]
Found 10 outliers among 100 measurements (10.00%)
1 (1.00%) low severe
5 (5.00%) low mild
4 (4.00%) high mildtransfer/walltime/pacing-false/same-seed time: [2.0228 ms 2.0239 ms 2.0252 ms]
thrpt: [1.9289 GiB/s 1.9301 GiB/s 1.9311 GiB/s]transfer/walltime/pacing-false/varying-seeds time: [2.0038 ms 2.0049 ms 2.0062 ms]
thrpt: [1.9471 GiB/s 1.9484 GiB/s 1.9494 GiB/s]transfer/walltime/pacing-true/same-seed time: [2.0328 ms 2.0343 ms 2.0362 ms]
thrpt: [1.9184 GiB/s 1.9202 GiB/s 1.9216 GiB/s]transfer/walltime/pacing-true/varying-seeds time: [2.0170 ms 2.0186 ms 2.0207 ms]
thrpt: [1.9331 GiB/s 1.9351 GiB/s 1.9366 GiB/s]Instructions per cycleCriterion reported no significant timing changes. All benchmarks
Profiles for profiler.firefox.com (64)
Download data for |
Client/server transfer resultsPerformance differences relative to d245301. Transfer of 33554432 bytes over loopback, min. 100 runs. All unit-less numbers are in milliseconds.
Table above only shows statistically significant changes. See all results below. All resultsTransfer of 33554432 bytes over loopback, min. 100 runs. All unit-less numbers are in milliseconds.
Download data for |
User-visible changes since v0.33.0: - Expose the outgoingMaxBufferedDatagrams and outgoingMaxAge setters as production API: mozilla#3990 - Expose the outgoing WebTransport datagram queue capacity per session: mozilla#4037 - Expose the per-datagram overhead in the datagram queue capacity: mozilla#4067 - Report the fate of outgoing WebTransport datagrams via aggregate stats: mozilla#4091 - Count datagrams actually sent per session: mozilla#4030 - Count a session's expired outgoing WebTransport datagrams: mozilla#3986 - Return NotAvailable instead of TooMuchData when the peer has no datagram path: mozilla#3989 - Put ABE (RFC 8511) behind a pref: mozilla#4090 - Add a log-payload feature: mozilla#4046 - Remove the deprecated ConnectionError alias: mozilla#4089 - Answer every PATH_CHALLENGE received on a path: mozilla#4101 - Honor a peer's minimum ACK delay above 50ms: mozilla#4068 - Use version-specific key update labels: mozilla#4080 - Compute QPACK MaxEntries from the peer's capacity: mozilla#4033 - Stop connection ID generation when the generator is exhausted: mozilla#4082 - Pad to the PMTUD probe size only when sending a probe: mozilla#3964 - Ignore ACKs of stale PMTUD probes: mozilla#4088
User-visible changes since v0.33.0: - Expose the outgoingMaxBufferedDatagrams and outgoingMaxAge setters as production API: [mozilla#3990](mozilla#3990) - Expose the outgoing WebTransport datagram queue capacity per session: [mozilla#4037](mozilla#4037) - Expose the per-datagram overhead in the datagram queue capacity: [mozilla#4067](mozilla#4067) - Report the fate of outgoing WebTransport datagrams via aggregate stats: [mozilla#4091](mozilla#4091) - Count datagrams actually sent per session: [mozilla#4030](mozilla#4030) - Count a session's expired outgoing WebTransport datagrams: [mozilla#3986](mozilla#3986) - Return NotAvailable instead of TooMuchData when the peer has no datagram path: [mozilla#3989](mozilla#3989) - Put ABE (RFC 8511) behind a pref: [mozilla#4090](mozilla#4090) - Add a log-payload feature: [mozilla#4046](mozilla#4046) - Remove the deprecated ConnectionError alias: [mozilla#4089](mozilla#4089) - Answer every PATH_CHALLENGE received on a path: [mozilla#4101](mozilla#4101) - Honor a peer's minimum ACK delay above 50ms: [mozilla#4068](mozilla#4068) - Use version-specific key update labels: [mozilla#4080](mozilla#4080) - Compute QPACK MaxEntries from the peer's capacity: [mozilla#4033](mozilla#4033) - Stop connection ID generation when the generator is exhausted: [mozilla#4082](mozilla#4082) - Pad to the PMTUD probe size only when sending a probe: [mozilla#3964](mozilla#3964) - Ignore ACKs of stale PMTUD probes: [mozilla#4088](mozilla#4088)

Re-land of #3991, which was merged into #4030's branch instead of main by mistake. Content is unchanged from the approved version.
Adds SessionStats::datagrams_sent_outgoing/datagrams_dropped_outgoing, backed by the per-session sent count from the previous commit, so that once a session's queue is empty, every datagram a caller handed in has been counted as sent, expired or dropped exactly once. Dropped covers byte-budget evictions, datagrams refused at enqueue as the lowest priority, datagrams dropped at packet-build time as too big for the path MTU, and datagrams still queued when the session closes. The Capsule fallback counts as sent on write.
close_session flushes the sent count and drops what is still queued before snapshotting the stats it returns, so the final values include the datagrams that call discards; a close or reset from the peer drops and counts the queue too. Both close paths expire stale datagrams first, so those count as expired rather than dropped. The per-tick sweep only visits the sessions the transport reports as having work.