Skip to content

feat(engine): adaptive buffer-sizing PID controller (#2095)#3952

Merged
oferchen merged 1 commit into
masterfrom
feat/adaptive-buffer-controller-2095
May 7, 2026
Merged

feat(engine): adaptive buffer-sizing PID controller (#2095)#3952
oferchen merged 1 commit into
masterfrom
feat/adaptive-buffer-controller-2095

Conversation

@oferchen
Copy link
Copy Markdown
Owner

@oferchen oferchen commented May 7, 2026

Summary

  • Implements the PID-style buffer-size controller described in the design RFC at docs/design/adaptive-buffer-controller.md (task Refactor xtask util helpers into modular modules #2095, follows Support daemon alias invocation #2094).
  • Ships the standalone AdaptiveBufferController and builder-style ControllerConfig in crates/engine/src/local_copy/buffer_pool/buffer_controller.rs with Ziegler-Nichols LAN-preset default gains (K_p=0.6, K_i=0.2, K_d=0.05). The recommended buffer size is exposed via an AtomicUsize for lock-free reads; PID state is guarded by a single std::sync::Mutex updated on the sample interval.
  • Anti-windup, dt clamping (1 ms .. 5 s), and [min_size, max_size] clamps mirror RFC sections 3.2-3.4. A pub(crate) observe_at(throughput, now) testing hook makes the controller deterministic; production code calls the observe(...) wrapper that uses Instant::now().

Out of scope: integration into BufferPool capacity, write-batch sizing, and multiplex frame batching. That wiring lands under the follow-up task #2096.

The RFC cites pipeline/buffer_controller.rs, but the engine crate has no pipeline module; placing the file alongside throughput.rs keeps the module tree flat. The deviation is documented at the top of the new file.

Test plan

  • CI fmt + clippy
  • CI nextest (stable) - 12 new unit tests in buffer_controller::tests covering proportional growth/shrink, integral steady-state error elimination, derivative damping, anti-windup clamping, both buffer-size clamps, reset semantics, zero-dt safety, default-gain convergence within 50 samples on a synthetic linear-saturating plant, builder defaults, bounded-output invariant across edge inputs, and reset preserving the recommended buffer size
  • CI Windows / macOS / Linux musl (no platform-specific code; Instant, AtomicUsize, Mutex are cross-platform)

@github-actions github-actions Bot added the enhancement New feature or request label May 7, 2026
@oferchen oferchen force-pushed the feat/adaptive-buffer-controller-2095 branch from b934d7a to 3c0ba93 Compare May 7, 2026 20:07
Add a PID-style controller that adapts per-pipeline buffer window size
in response to observed throughput, per the design RFC at
docs/design/adaptive-buffer-controller.md.

The new module exposes AdaptiveBufferController and a builder-style
ControllerConfig with Ziegler-Nichols LAN-preset gains as defaults
(K_p=0.6, K_i=0.2, K_d=0.05). Internally a single std::sync::Mutex
guards the integrator, previous-error sample, and previous-sample
timestamp; the recommended buffer size is exposed via an AtomicUsize
for lock-free reads from the hot path. The dt is clamped to [1ms, 5s]
to defend against divide-by-zero on the derivative term and integral
windup on a stalled producer; the integrator is independently clamped
by the configured anti-windup window.

Tests cover proportional growth/shrink, integral steady-state-error
elimination, derivative damping on a step input, anti-windup clamping
under sustained error, both buffer-size clamps, reset semantics,
zero-dt safety, and a synthetic-plant convergence test against a
linear-saturating throughput model that confirms the default gains
settle within 10% of the setpoint inside 50 samples.

Integration into write-batch sizing, BufferPool capacity hints, and
multiplex frame batching is intentionally out of scope; that work is
tracked by the wiring follow-up under task #2096.

The RFC originally proposed crates/engine/src/pipeline/buffer_controller.rs,
but the engine crate has no pipeline module today; placing the file
alongside throughput.rs keeps the module tree flat and groups it with
the existing throughput EMA it will eventually consume. The deviation
is documented in the file's top doc comment.
@oferchen oferchen force-pushed the feat/adaptive-buffer-controller-2095 branch from 3c0ba93 to 1bf8c2b Compare May 7, 2026 20:22
@oferchen oferchen merged commit 8e8c71d into master May 7, 2026
23 of 39 checks passed
@oferchen oferchen deleted the feat/adaptive-buffer-controller-2095 branch May 8, 2026 03:46
oferchen added a commit that referenced this pull request May 18, 2026
Add a PID-style controller that adapts per-pipeline buffer window size
in response to observed throughput, per the design RFC at
docs/design/adaptive-buffer-controller.md.

The new module exposes AdaptiveBufferController and a builder-style
ControllerConfig with Ziegler-Nichols LAN-preset gains as defaults
(K_p=0.6, K_i=0.2, K_d=0.05). Internally a single std::sync::Mutex
guards the integrator, previous-error sample, and previous-sample
timestamp; the recommended buffer size is exposed via an AtomicUsize
for lock-free reads from the hot path. The dt is clamped to [1ms, 5s]
to defend against divide-by-zero on the derivative term and integral
windup on a stalled producer; the integrator is independently clamped
by the configured anti-windup window.

Tests cover proportional growth/shrink, integral steady-state-error
elimination, derivative damping on a step input, anti-windup clamping
under sustained error, both buffer-size clamps, reset semantics,
zero-dt safety, and a synthetic-plant convergence test against a
linear-saturating throughput model that confirms the default gains
settle within 10% of the setpoint inside 50 samples.

Integration into write-batch sizing, BufferPool capacity hints, and
multiplex frame batching is intentionally out of scope; that work is
tracked by the wiring follow-up under task #2096.

The RFC originally proposed crates/engine/src/pipeline/buffer_controller.rs,
but the engine crate has no pipeline module today; placing the file
alongside throughput.rs keeps the module tree flat and groups it with
the existing throughput EMA it will eventually consume. The deviation
is documented in the file's top doc comment.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant