@@ -1651,13 +1651,36 @@ async fn tunnel_loop(
16511651}
16521652
16531653/// Maximum number of `data` ops a pipelined session keeps in flight
1654- /// at any one time. Two parallel batches per session is enough to
1655- /// overlap one Apps Script round-trip with the next on a single TCP
1656- /// stream — that's the throughput win. Higher depths run into
1657- /// diminishing returns (server-side seq enforcement serializes the
1658- /// drains anyway) and burn more Apps Script quota on speculative
1659- /// polls when a session goes idle.
1660- const PIPELINE_DEPTH : usize = 2 ;
1654+ /// at any one time. Matches the TLS connection-pool minimum so a
1655+ /// single active session can fill every warm connection's transit
1656+ /// window when client→Apps Script is the dominant leg (the censored-
1657+ /// network case this project is built for).
1658+ ///
1659+ /// Server-side processing stays serial via the per-session seq lock,
1660+ /// so this depth doesn't translate to parallel upstream writes — but
1661+ /// it does parallelize the slow client↔AS leg's RTT. With depth=8 the
1662+ /// slow leg is used for ~8 ops simultaneously instead of one at a
1663+ /// time, which is the actual bottleneck in throttled networks.
1664+ ///
1665+ /// Costs that grow with depth:
1666+ /// * Client-side reorder-buffer memory: one oneshot receiver per
1667+ /// in-flight op, bounded by depth. With 64 KB chunks the per-
1668+ /// session worst case is `depth × 64 KB` of payload sitting in
1669+ /// the mux pipeline.
1670+ /// * Per-deployment semaphore pressure: a single session can
1671+ /// occupy up to `depth` of a deployment's 30 concurrent slots
1672+ /// (or spread across deployments via `next_script_id`
1673+ /// round-robin). With many active pipelined sessions this can
1674+ /// contend with new connects.
1675+ /// * Seq-loss cascade: if seq=N is permanently lost (rare —
1676+ /// requires the carrying batch to never reach the server), all
1677+ /// subsequent in-flight seqs wait `SEQ_WAIT_TIMEOUT` for it
1678+ /// before failing.
1679+ ///
1680+ /// Idle sessions stay at depth=1 regardless of this constant — see
1681+ /// `target_depth` in `tunnel_loop_pipelined` — so the quota cost of
1682+ /// raising this only applies to actively-streaming sessions.
1683+ const PIPELINE_DEPTH : usize = 8 ;
16611684
16621685/// Pipelined variant of `tunnel_loop`: keeps up to `PIPELINE_DEPTH`
16631686/// `data` ops in flight per session, each tagged with a per-session
@@ -2547,8 +2570,8 @@ mod tests {
25472570 } ) ;
25482571
25492572 // Receive both ops back-to-back. Loop sends them before
2550- // entering the receive phase because PIPELINE_DEPTH=2 and
2551- // both reads succeed in the send phase.
2573+ // entering the receive phase: target_depth ≥ 2 (PIPELINE_DEPTH)
2574+ // and both reads succeed in the send phase.
25522575 let msg0 = tokio:: time:: timeout ( Duration :: from_secs ( 2 ) , rx. recv ( ) )
25532576 . await
25542577 . expect ( "first op not emitted" )
0 commit comments