pub struct LimitBand {
pub min: usize,
pub max: usize,
}Expand description
The range the governed limit is clamped to.
Spelled as a type rather than two constants because it has to be narrowed
by an operator’s configured ceiling: a server told --max-concurrent-transfers 4
must serve 4, not the design’s floor of 10. See LimitBand::for_ceiling.
Fields§
§min: usizeThe smallest the controller may shrink to.
max: usizeThe largest it may grow to, and where it starts.
Implementations§
Source§impl LimitBand
impl LimitBand
Sourcepub fn for_ceiling(ceiling: usize) -> LimitBand
pub fn for_ceiling(ceiling: usize) -> LimitBand
The band for a server whose operator pinned a hard ceiling.
The operator’s number is the ceiling, and the FLOOR is clamped under it:
pinning 4 gives [4, 4], a governor that cannot move, which is exactly
what “I told you 4” should mean. A configured ceiling below
MIN_LIMIT must not be silently RAISED — a gate admitting more than
it was told to is the one failure mode a limit may not have.
The ceiling is NOT capped at MAX_LIMIT, and that was a bug. The
first form did MAX_LIMIT.min(ceiling), so a server configured with the
shipped default of 256 got a band of [10, 100] and quietly served 100.
Lowering an operator’s explicit number is the same defect as raising it,
in the other direction: both mean the configured value is not the value.
MAX_LIMIT is the design’s default for a server that has NOT been told a
number — it is not an opinion that outranks one that has.
Sourcepub fn for_budget(budget: usize) -> LimitBand
pub fn for_budget(budget: usize) -> LimitBand
The band for a server whose ceiling is a declared, measured budget rather than a round number an operator typed.
§Why the floor moves with the ceiling — MEASURED
LimitBand::for_ceiling pins the floor at MIN_LIMIT = 10. With the
shipped ceiling of 256 that is a band of [10, 256], and the controller
walks the whole of it: multiplicative decrease is limit -= limit/8, so
256 → 224 → 196 → … → 24 → 21 → 19 → 17 … On the appliance under a
64-client push storm every 100 ms window stands, and the measurement
took the gate refusing by name at exactly that — already serving its limit of 19, 268 of 1000 push-creates admitted. 19 was not a constant
anybody chose; it is a point on a descent.
The descent does not stop because shedding does not fix what the controller is measuring. The sojourn it reads was the gap between admission and the spawned task’s first line — the tokio ready queue and the blocking-pool handoff — and that gap is set by how many clients are connected and doing crypto, not by how many transfers are admitted. A refused client reconnects, so a refusal makes the input worse. A controller with no authority over its own input runs to its floor.
Both halves are fixed here. The controller’s input is now the
admission wait — the queue this gate actually owns
(DEFAULT_ADMISSION_WAIT) — and its floor is a share of the budget
rather than a constant: below BUDGET_FLOOR_DENOMINATOR⁻¹ of a
number derived from cores, descriptors and MemAvailable, the box is
provably not the bottleneck and refusing costs more than serving.
Trait Implementations§
impl Copy for LimitBand
impl Eq for LimitBand
impl StructuralPartialEq for LimitBand
Auto Trait Implementations§
impl Freeze for LimitBand
impl RefUnwindSafe for LimitBand
impl Send for LimitBand
impl Sync for LimitBand
impl Unpin for LimitBand
impl UnsafeUnpin for LimitBand
impl UnwindSafe for LimitBand
Blanket Implementations§
impl<T> Allocation for T
Source§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.