Skip to content

fix: stop adaptive pacing from compounding its own rate limit - #21

Merged
cppla merged 1 commit into
mainfrom
codex/adaptive-pacing-feedback
Sep 22, 2026
Merged

cppla merged 1 commit into
mainfrom
codex/adaptive-pacing-feedback

Conversation

@cppla

@cppla cppla commented Sep 22, 2026 •

Copy link
Copy Markdown
Owner

Summary

Fix sustained native QUIC transfers progressively reducing their own adaptive pacing target under a persistent RTT penalty.

  • Measure actual token-deficit sleep of the single admission owner, including in-progress sleeps, without adding queued writers' overlapping Wait durations.
  • Use the controller's own clock for pacing-share baselines; keep transport timestamps for delivery-rate observations.
  • In pacing-dominated intervals, lower rates no longer replace the unpenalized bandwidth history. Higher observations still qualify, and current RTT/loss penalties still apply.
  • Keep transport-bound capacity decreases and recovery, counter resets, cancellation/refunds, fixed-rate and bypass behavior.
  • Keep an initial prior only while capacity history is empty and the sample is pacing-limited. Do not subtract token waiting from the delivery-rate denominator.
  • Document the application-level heuristic and the remaining limits of capacity probing.

No wire protocol, authentication, dependency, configuration default, minimum rate, gain, version or release change.

Verification

  • Final local make check and make race: passed on the final source.
  • Local make stealth-tools-check: passed; no packet-capture campaign was run.
  • Deterministic regressions cover all profiles, persistent RTT, independent loss/RTT penalties, empty history, capacity decrease/recovery, actual sleep accounting, concurrent waiters, ongoing/sub-window samples, exact half-window boundary, zero-clock origin, interrupted sleeps and epoch resets.
  • Production Controller fake-clock phases call real Wait and independently advance synthetic wire time. They verify lower path-capacity samples reenter history after a step-down, and RTT/path recovery remains possible.
  • Real loopback QUIC regressions cover an 8 MiB byte-verified sustained download and two shared streams with fixed small receive windows, actual token-sleep/blocked-write overlap, full-connection backpressure and recovery.
  • The shared-stream test requires target reduction beyond both balanced-profile penalty floors combined, so a penalty-only change cannot satisfy its capacity-change assertion.
  • A negative-control overlay using the complete original controller/estimator from 57e431f fails the sustained-download test at the default 65,536 bytes/s floor. Its test-only deadline is 12 s instead of the formal fixture's 15 s to allow bounded cleanup; this is not a same-budget throughput benchmark.
  • One unchanged same-client diagnostic completed a 4 MiB upload in 0.611 s and a 4 MiB download in 0.493 s, including acknowledgements; the download progressed approximately linearly. This is a single local diagnostic, not a general speed claim.

Evidence limits

The real QUIC fixtures test the adapter/controller, not native authentication or serverCore. Sleep share is an application-level heuristic, not transport-level proof of uncongested capacity. Sustained RTT penalties can still limit discovery of spare capacity; this change does not add a full bandwidth-probing state machine. No passive-traffic, browser-equivalence, separate remote-host or comparative-performance claim is made. Raw diagnostics remain ignored and local.

Exact PR head aa02a4d6e433d6c02b47270e13d3e46b39f7a1a2 passed CI, CodeQL, and Linux namespace/netem integration. CI includes Linux/macOS tests, race detection, reachable vulnerability scanning, four-platform builds, actual Docker integration and a multi-platform OCI image build. No open review threads or change requests were present at merge preparation.

Post-merge verification: main commit 87d199982916f73452678869466249edafa7ed65 has the identical source tree 2b8e3b95ffb63bc3b00f6651b2175c4b74ab7a62 and passed its own push-triggered CI, CodeQL and Linux namespace/netem integration. No tag or release was created.

Copilot AI lite review requested due to automatic review settings September 22, 2026 14:13
@cppla
cppla merged commit 87d1999 into main Sep 22, 2026
14 checks passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Adjust the pacing-sleep test fixture so its delay is strictly beyond half the observation interval.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 High severity

Open (1)
What changed in this PR

Fixes adaptive QUIC pacing so self-imposed token waits do not recursively reduce estimated capacity.

Changes:

  • Tracks pacing sleep using the controller clock.
  • Preserves capacity history during pacing-limited intervals.
  • Adds regression tests and documents the heuristic and limitations.
File Summary
internal/​tunnel/​pacing_feedback_integration_test.go Adds QUIC pacing and recovery regressions.
internal/​accel/​pacing_sleep_test.go Tests sleep accounting; critical issue at line 232: the fixture is exactly half pacing time, so the expected classification fails.
internal/​accel/​pacer.go Adds pacing-sleep accounting and classification.
internal/​accel/​adaptive.go Preserves capacity history for pacing-limited samples.
internal/​accel/​adaptive_feedback_test.go Tests estimator history and penalty behavior.
docs/​ARCHITECTURE.md Documents adaptive pacing behavior.
docs/​ACCELERATION.md Documents the heuristic and limitations.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

var externalWork time.Duration
switch condition {
case "mostly_transport":
externalWork = time.Second
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.

2 participants