feat(engine): AIMD concurrency limiter type#3951
Merged
Merged
Conversation
Adds the standalone limiter type defined by the design RFC at docs/design/aimd-concurrency-limiter.md. The implementation lives in crates/engine/src/concurrent_delta/work_queue/limiter.rs and exposes: - LimiterConfig builder with min_limit / max_limit / alpha / beta_num / beta_den / build(). - AimdLimiter with try_acquire, target, in_flight, rtt_ema_nanos, and a pub is_rtt_spike predicate. - RAII Ticket guard (#[must_use]) with record_success / record_overload / record_error and Drop fallback for panic paths. - OverloadReason variants for RttSpike / QueueSaturated / DiskCommitPressure / ErrorRate. Internals follow the RFC: integer-only RTT EMA (alpha_ema = 1/8 per RFC 6298), variance smoothed with beta = 1/4, RTT-spike threshold of ema + 2*sqrt(var) via Newton-method isqrt, slow-start doubling until the first decrease, debounce window of 2*rtt_ema after each multiplicative decrease, and AcqRel/Acquire atomic ordering on every target/in_flight transition. Twelve unit tests cover the algorithm: target saturation (single threaded and under thread contention), additive increase, multiplicative decrease, min/max clamps, debounce suppression, RTT EMA convergence, ticket Drop on panic, transient-vs-deterministic error classification, slow-start doubling, RTT-spike predicate, builder clamps, and the isqrt helper. Not yet integrated. Callers (WorkQueueSender, disk-commit, CLI) are wired in the follow-on tickets: - #2092: convergence tests under injected error. - #2093: --adaptive-concurrency / --no-adaptive-concurrency CLI flag.
bfc0c39 to
acdb8cf
Compare
oferchen
added a commit
that referenced
this pull request
May 18, 2026
* feat(engine): AIMD concurrency limiter type (#2091) Adds the standalone limiter type defined by the design RFC at docs/design/aimd-concurrency-limiter.md. The implementation lives in crates/engine/src/concurrent_delta/work_queue/limiter.rs and exposes: - LimiterConfig builder with min_limit / max_limit / alpha / beta_num / beta_den / build(). - AimdLimiter with try_acquire, target, in_flight, rtt_ema_nanos, and a pub is_rtt_spike predicate. - RAII Ticket guard (#[must_use]) with record_success / record_overload / record_error and Drop fallback for panic paths. - OverloadReason variants for RttSpike / QueueSaturated / DiskCommitPressure / ErrorRate. Internals follow the RFC: integer-only RTT EMA (alpha_ema = 1/8 per RFC 6298), variance smoothed with beta = 1/4, RTT-spike threshold of ema + 2*sqrt(var) via Newton-method isqrt, slow-start doubling until the first decrease, debounce window of 2*rtt_ema after each multiplicative decrease, and AcqRel/Acquire atomic ordering on every target/in_flight transition. Twelve unit tests cover the algorithm: target saturation (single threaded and under thread contention), additive increase, multiplicative decrease, min/max clamps, debounce suppression, RTT EMA convergence, ticket Drop on panic, transient-vs-deterministic error classification, slow-start doubling, RTT-spike predicate, builder clamps, and the isqrt helper. Not yet integrated. Callers (WorkQueueSender, disk-commit, CLI) are wired in the follow-on tickets: - #2092: convergence tests under injected error. - #2093: --adaptive-concurrency / --no-adaptive-concurrency CLI flag. * style: cargo fmt --all * fix(engine): clippy lints on AIMD limiter (abs_diff, div_ceil, format args)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
docs/design/aimd-concurrency-limiter.md(Use branded constants in daemon wrapper tests #2090). The implementation lives atcrates/engine/src/concurrent_delta/work_queue/limiter.rsand is exported fromwork_queue/mod.rsasAimdLimiter,LimiterConfig,OverloadReason, andTicket.stdimplementation:AtomicUsize/AtomicU32/AtomicU64for state,Instant+OnceLockfor the monotonic epoch, integer-only RTT EMA per RFC 6298 (alpha_ema = 1/8), Newton-methodisqrtfor the RTT-spike sigma threshold. No new dependencies, nounsafe.Ticketis#[must_use], consumed byrecord_success/record_overload/record_error. TheDropfallback releasesin_flightwithout disturbingtargetor the EMA so a panicking worker cannot leak the slot.AcqRelfor thetry_acquireCAS and counter mutations,Releasefor state publishes,Acquirefor state reads. NoRelaxedontarget.WorkQueueSender::sendand the disk-commitWriterPressurereporter arrives with Remove legacy daemon wrappers #2092 (convergence tests under injected error). The--adaptive-concurrency/--no-adaptive-concurrencyCLI flag is Brand version banners around oc-rsync #2093.Test plan
Twelve unit tests inside
limiter.rs::testscover the algorithm:isqrt_matches_floor_sqrt- Newton iteration matchesfloor(sqrt(n))for boundary, mid-range, and near-u64::MAXinputs.acquire_respects_target-try_acquirereturnsNoneoncein_flight == target, and arecord_successre-opens the slot.acquire_saturation_under_threads- two threads racing on a one-slot limiter never exceedtargetandin_flightreturns to 0 after the join.additive_increase_after_target_successes-alpha = 1adds one slot per completed window in steady state.multiplicative_decrease_halves_target_on_overload-beta = 1/2halvestargetonrecord_overload.decrease_clamped_to_min_limit- decrease saturates atmin_limit.increase_clamped_to_max_limit- increase saturates atmax_limit.debounce_suppresses_back_to_back_decreases- second overload inside the2 * rtt_emawindow leavestargetunchanged.rtt_ema_smoothing_converges- 10 baseline + 20 stress samples settle the EMA in[9.0ms, 9.5ms], matching the analytic geometric tail of(7/8)^20.ticket_drop_on_panic_decrements_in_flight-panic::catch_unwindconfirms theDropfallback releases the slot without changingtarget.error_kind_classification-WouldBlock/Interruptedhalvetarget;NotFound/PermissionDeniedkeeptargetuntouched per design section 3.4 item 3.slow_start_doubles_until_first_decrease- target doubles 2 -> 4 -> 8 in slow-start, halves to 4 on first overload, then grows additively (4 -> 5) instead of doubling.rtt_spike_predicate- returns false with no samples, false at the EMA, true at a 100x outlier.config_builder_clamps_initial_target- builder clamps an out-of-rangeinitial_targetinto[min_limit, max_limit].CI (fmt + clippy + nextest on Linux/macOS/Windows) is the test runner per the contributing guide; nothing was run locally.