Files
amethyst/quic
Claude bc19e90c17 fix(quic-interop): batch enqueue + single wakeup per multiplex chunk
Diagnosis from qlog timeline pattern: send packets clustered ~37ms
apart (sim RTT) but each cluster contained only ONE stream's data
(80-byte packets despite 1452-byte capacity). 1457 GETs in 58s, ~25
streams/sec.

Root cause: race between client.get()'s per-call driver.wakeup() and
the dispatcher scheduling the OTHER 63 coroutines. Sequence:
  1. c1 acquires conn lock, enqueues request, wakes send loop, releases
  2. Send loop wakes, queues for lock — other 63 coroutines haven't
     started yet (dispatcher hasn't picked them up)
  3. Send loop acquires lock alone, drains c1's data into one tiny
     packet, releases
  4. c2 finally starts, acquires, enqueues, wakes...
  → one stream per packet, no coalescing

Fix: split GetClient.get() into prepareRequest (open + enqueue + FIN,
synchronous, no wake) and awaitResponse (collect, async). Multiplex
chunk loop now:
  Phase 1: serial prepareRequest for every URL in the chunk (64 in
           sequence, each adding to send buffers)
  Phase 2: SINGLE driver.wakeup() — by now all 64 streams have data
           queued; send loop drains them all in coalesced packets
  Phase 3: parallel awaitResponse with per-stream timeout

Predicted throughput jump: 25 streams/sec → ~1000+/sec (sim RTT-bound
at ~30ms per round trip = 64 streams per RTT = 2100/sec ceiling).

Single-request paths (transfer / chacha20 / etc) keep using the
default GetClient.get() which still wraps prepare+await; no behavioral
change there.

https://claude.ai/code/session_01HcvfQq1ttPV9PkRoJb4nyT
2026-05-07 01:57:47 +00:00
..