pub mod builder;
pub mod controller;
pub mod law;
pub mod settings;
pub mod sim;
pub mod strategy;
use core::time::Duration;
use alloc::boxed::Box;
pub use builder::ConcurrencyBuilder;
pub use controller::{ConcurrencyController, WorkerPool};
pub use law::{ControlLaw, Law, LawKind};
pub use settings::{ConcurrencySettings, Window};
pub use strategy::{Concurrency, ConcurrencyStrategy, Preset, Strategy, StrategyDescriptor};
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Sample {
pub concurrency: usize,
pub throughput: f64,
pub cov: f64,
pub rtt_min: Duration,
pub rtt_p50: Duration,
pub rtt_p99: Duration,
pub util: f64,
}
impl Sample {
#[must_use]
pub fn seed(concurrency: usize) -> Self {
Self {
concurrency,
throughput: 0.0,
cov: 0.0,
rtt_min: Duration::ZERO,
rtt_p50: Duration::ZERO,
rtt_p99: Duration::ZERO,
util: 0.0,
}
}
}
pub enum Signal {
Builtin(SignalKind),
Custom(Box<dyn Fn(&Sample) -> f64 + Send>),
}
impl core::fmt::Debug for Signal {
fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::Builtin(kind) => write!(formatter, "Signal::Builtin({kind:?})"),
Self::Custom(_) => formatter.write_str("Signal::Custom(<fn>)"),
}
}
}
impl Signal {
#[must_use]
pub fn read(&self, sample: &Sample) -> f64 {
match self {
Self::Builtin(kind) => kind.read(sample),
Self::Custom(extract) => extract(sample),
}
}
#[must_use]
pub fn class(&self) -> SignalClass {
match self {
Self::Builtin(kind) => SignalClass::Builtin(*kind),
Self::Custom(_) => SignalClass::Custom,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SignalKind {
Throughput,
LatencyP99,
LatencyGradient,
Utilization,
Cov,
}
impl SignalKind {
#[must_use]
fn read(self, sample: &Sample) -> f64 {
match self {
Self::Throughput => sample.throughput,
Self::LatencyP99 => duration_millis(sample.rtt_p99),
Self::LatencyGradient => latency_gradient(sample),
Self::Utilization => sample.util,
Self::Cov => sample.cov,
}
}
#[must_use]
pub fn is_latency(self) -> bool {
matches!(self, Self::LatencyP99 | Self::LatencyGradient)
}
#[must_use]
pub fn is_maximizable(self) -> bool {
matches!(self, Self::Throughput | Self::Utilization)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SignalClass {
None,
Builtin(SignalKind),
Custom,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Objective {
Maximize,
Target(f64),
Ceiling(f64),
Knee,
Hold(usize),
}
impl Objective {
#[must_use]
pub fn default_law(self) -> LawKind {
match self {
Self::Maximize => LawKind::HillClimb,
Self::Target(_) => LawKind::Proportional,
Self::Ceiling(_) => LawKind::Aimd,
Self::Knee => LawKind::Multiplicative,
Self::Hold(_) => LawKind::HillClimb,
}
}
pub fn coherent_with(self, signal: SignalClass) -> Result<(), &'static str> {
match self {
Self::Maximize => match signal {
SignalClass::Builtin(kind) if kind.is_maximizable() => Ok(()),
SignalClass::Custom => Ok(()),
SignalClass::None => Err("maximize objective names no signal to climb"),
SignalClass::Builtin(_) => Err("maximize needs a throughput/utilization signal"),
},
Self::Knee => match signal {
SignalClass::Builtin(kind) if kind.is_latency() => Ok(()),
_ => Err("knee objective requires a latency signal (gradient or p99)"),
},
Self::Target(value) | Self::Ceiling(value) => {
if !value.is_finite() || value <= 0.0 {
return Err("target/ceiling value must be finite and positive");
}
match signal {
SignalClass::None => Err("target/ceiling objective names no signal to read"),
_ => Ok(()),
}
}
Self::Hold(_) => match signal {
SignalClass::None => Ok(()),
_ => Err("hold objective must not name a signal"),
},
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Gate {
pub coefficient_of_variation_threshold: f64,
pub window: Duration,
pub reprobe: u32,
}
impl Default for Gate {
fn default() -> Self {
Self {
coefficient_of_variation_threshold: 0.05,
window: Duration::from_millis(150),
reprobe: 1,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Bounds {
pub min: usize,
pub max: usize,
pub start: usize,
}
impl Default for Bounds {
fn default() -> Self {
Self {
min: 1,
max: 512,
start: 16,
}
}
}
impl Bounds {
pub fn validate(&self) -> Result<(), &'static str> {
if self.min < 1 {
return Err("bounds.min must be >= 1");
}
if self.min > self.max {
return Err("bounds.min must be <= bounds.max");
}
if self.start < self.min || self.start > self.max {
return Err("bounds.start must lie within [min, max]");
}
Ok(())
}
#[must_use]
pub fn clamp(&self, n: usize) -> usize {
n.clamp(self.min, self.max)
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct LawStep {
pub current: usize,
pub signal: f64,
pub prev_signal: f64,
pub objective: Objective,
pub cov: f64,
pub coefficient_of_variation_threshold: f64,
pub min: usize,
pub max: usize,
}
impl LawStep {
#[must_use]
pub fn significant(&self) -> bool {
(self.signal - self.prev_signal).abs() > self.margin()
}
#[must_use]
pub fn margin(&self) -> f64 {
self.coefficient_of_variation_threshold * self.signal.abs()
}
#[must_use]
pub fn delta(&self) -> f64 {
self.signal - self.prev_signal
}
#[must_use]
pub fn clamp(&self, n: usize) -> usize {
n.clamp(self.min, self.max)
}
#[must_use]
pub fn stepped(&self, delta: isize) -> usize {
let raw = self.current as isize + delta;
self.clamp(raw.max(0) as usize)
}
}
#[must_use]
pub fn duration_millis(duration: Duration) -> f64 {
duration.as_secs_f64() * 1_000.0
}
#[must_use]
pub fn latency_gradient(sample: &Sample) -> f64 {
let p99 = sample.rtt_p99.as_secs_f64();
if p99 <= 0.0 {
return 1.0;
}
(sample.rtt_min.as_secs_f64() / p99).clamp(0.0, 1.0)
}
#[cfg(test)]
#[allow(clippy::unwrap_used, clippy::expect_used, clippy::float_cmp)]
mod tests {
use super::*;
fn sample_with(throughput: f64, p99_ms: u64, min_ms: u64, util: f64) -> Sample {
Sample {
concurrency: 8,
throughput,
cov: 0.05,
rtt_min: Duration::from_millis(min_ms),
rtt_p50: Duration::from_millis(min_ms),
rtt_p99: Duration::from_millis(p99_ms),
util,
}
}
#[test]
fn signal_reads_named_field_only() {
let sample = sample_with(1_000.0, 10, 2, 0.7);
assert_eq!(
Signal::Builtin(SignalKind::Throughput).read(&sample),
1_000.0
);
assert_eq!(Signal::Builtin(SignalKind::LatencyP99).read(&sample), 10.0);
assert_eq!(Signal::Builtin(SignalKind::Utilization).read(&sample), 0.7);
assert!((Signal::Builtin(SignalKind::LatencyGradient).read(&sample) - 0.2).abs() < 1e-9);
}
#[test]
fn custom_signal_can_ignore_sample() {
let signal = Signal::Custom(Box::new(|_| 42.0));
assert_eq!(signal.read(&Sample::seed(1)), 42.0);
assert_eq!(signal.class(), SignalClass::Custom);
}
#[test]
fn gradient_defaults_to_one_when_unprimed() {
assert_eq!(latency_gradient(&Sample::seed(4)), 1.0);
}
#[test]
fn coherence_rejects_maximize_without_signal() {
assert!(
Objective::Maximize
.coherent_with(SignalClass::None)
.is_err()
);
assert!(
Objective::Maximize
.coherent_with(SignalClass::Builtin(SignalKind::LatencyP99))
.is_err()
);
assert!(
Objective::Maximize
.coherent_with(SignalClass::Builtin(SignalKind::Throughput))
.is_ok()
);
}
#[test]
fn coherence_rejects_knee_without_latency_signal() {
assert!(
Objective::Knee
.coherent_with(SignalClass::Builtin(SignalKind::Throughput))
.is_err()
);
assert!(
Objective::Knee
.coherent_with(SignalClass::Builtin(SignalKind::LatencyGradient))
.is_ok()
);
}
#[test]
fn coherence_rejects_hold_with_signal_and_bad_target() {
assert!(
Objective::Hold(8)
.coherent_with(SignalClass::Builtin(SignalKind::Throughput))
.is_err()
);
assert!(Objective::Hold(8).coherent_with(SignalClass::None).is_ok());
assert!(
Objective::Target(f64::NAN)
.coherent_with(SignalClass::Builtin(SignalKind::LatencyP99))
.is_err()
);
}
#[test]
fn bounds_validate_and_clamp() {
assert!(
Bounds {
min: 1,
max: 8,
start: 4
}
.validate()
.is_ok()
);
assert!(
Bounds {
min: 8,
max: 4,
start: 4
}
.validate()
.is_err()
);
assert!(
Bounds {
min: 1,
max: 8,
start: 16
}
.validate()
.is_err()
);
assert_eq!(
Bounds {
min: 2,
max: 8,
start: 4
}
.clamp(100),
8
);
assert_eq!(
Bounds {
min: 2,
max: 8,
start: 4
}
.clamp(0),
2
);
}
#[test]
fn law_step_gate_rejects_sub_threshold_change() {
let step = LawStep {
current: 8,
signal: 101.0,
prev_signal: 100.0,
objective: Objective::Maximize,
cov: 0.05,
coefficient_of_variation_threshold: 0.10,
min: 1,
max: 64,
};
assert!(
!step.significant(),
"1% change under a 10% threshold is noise"
);
let big = LawStep {
signal: 130.0,
..step
};
assert!(big.significant(), "30% change clears the 10% threshold");
}
#[test]
fn law_step_stepped_saturates_and_clamps() {
let step = LawStep {
current: 1,
signal: 0.0,
prev_signal: 0.0,
objective: Objective::Maximize,
cov: 0.0,
coefficient_of_variation_threshold: 0.05,
min: 1,
max: 8,
};
assert_eq!(step.stepped(-5), 1, "saturates then clamps to min");
assert_eq!(step.stepped(100), 8, "clamps to max");
}
}