pub struct MemoryGovernor { /* private fields */ }Expand description
Process-wide byte-accounting governor for large allocations.
Every large planned allocation (dense design materialization, covariance
block, sampler design assembly) reserves its byte footprint against one
shared ledger via try_reserve and holds the returned
RAII MemoryReservation for as long as the allocation is live. Because
the ledger is shared, allocations that are each individually acceptable can
no longer jointly exceed memory: whichever request would tip the ledger
past the budget gets a typed MemoryReservationError and routes to a
chunked or matrix-free strategy instead. Strategy selection is thereby a
continuous function of predicted live bytes vs remaining budget, not of
row/column thresholds.
The global budget is sized once from this process’s stationary capacity
(host total memory, clamped by the binding cgroup’s hard limit inside
containers or under a job scheduler) — see GOVERNOR_BUDGET_NUMERATOR for
the headroom rationale and governor_budget_from_availability for why it
is not denominated in free memory (#2702).
Implementations§
Source§impl MemoryGovernor
impl MemoryGovernor
Sourcepub fn global() -> &'static MemoryGovernor
pub fn global() -> &'static MemoryGovernor
The process-wide governor. Budget detection runs once, on first use.
This OnceLock is where the process’s single availability observation
is taken; process_memory_availability hands the same observation to
every other planner rather than probing again.
pub fn reserved_bytes(&self) -> usize
Sourcepub fn remaining_bytes(&self) -> usize
pub fn remaining_bytes(&self) -> usize
Bytes still admissible: the budget less what is reserved by this process right now. The only quantity here that moves is this process’s own live governed footprint — which is the one thing a caller can actually route around.
Sourcepub fn single_materialization_cap_bytes(&self) -> usize
pub fn single_materialization_cap_bytes(&self) -> usize
Absolute ceiling for one governed operation: 3/4 of this process’s
memory capacity (min(host total, binding cgroup limit)).
This is a routing threshold — the question it answers is “could a
dense footprint this large ever live in this process?” — so it is
deliberately stationary. It is not the live budget: whether an
allocation fits right now is decided by Self::try_reserve against
the joint ledger, which returns a typed, routable refusal instead of an
abort. Since #2702 both are denominated in the same capacity, so the two
can only disagree because of a live reservation.
Returning the live budget here was gam#2684: the budget was 3/4 of
available memory, so a cgroup sitting at its limit drove this ceiling
continuously to zero (measured at 53,248 bytes available with 448 GB
free on the host), and every caller comparing a request against it —
including DenseDesignMatrix::to_dense, which panics on refusal —
refused allocations as small as a 300x12 design. Threshold-shaped
routing decisions taken from a moving quantity also make the chosen
route depend on what else the box was doing, which SPEC-20 forbids
(see process_memory_availability); one consumer even hashes this
cap into a basis cache key.
Sourcepub fn try_reserve(
&self,
bytes: usize,
context: &str,
) -> Result<MemoryReservation, MemoryReservationError>
pub fn try_reserve( &self, bytes: usize, context: &str, ) -> Result<MemoryReservation, MemoryReservationError>
Reserve bytes against the joint ledger.
On success the returned MemoryReservation must be held for as long
as the allocation it accounts for is live; dropping it releases the
bytes. On failure the caller receives the ledger evidence and is
expected to fall back to a chunked or matrix-free strategy.
Sourcepub fn try_reserve_dense_f64(
&self,
nrows: usize,
ncols: usize,
context: &str,
) -> Result<MemoryReservation, MemoryReservationError>
pub fn try_reserve_dense_f64( &self, nrows: usize, ncols: usize, context: &str, ) -> Result<MemoryReservation, MemoryReservationError>
Reserve the footprint of a dense nrows × ncols f64 matrix.
Dimension-product overflow is reported as a budget refusal (an
allocation whose size cannot even be computed certainly does not fit).
Sourcepub fn try_reserve_dense_f64_copies(
&self,
nrows: usize,
ncols: usize,
copies: usize,
context: &str,
) -> Result<MemoryReservation, MemoryReservationError>
pub fn try_reserve_dense_f64_copies( &self, nrows: usize, ncols: usize, copies: usize, context: &str, ) -> Result<MemoryReservation, MemoryReservationError>
Reserve the predicted live footprint of copies simultaneous dense
matrices with one atomic ledger charge.
Trait Implementations§
Source§impl Clone for MemoryGovernor
impl Clone for MemoryGovernor
Source§fn clone(&self) -> MemoryGovernor
fn clone(&self) -> MemoryGovernor
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl Freeze for MemoryGovernor
impl RefUnwindSafe for MemoryGovernor
impl Send for MemoryGovernor
impl Sync for MemoryGovernor
impl Unpin for MemoryGovernor
impl UnsafeUnpin for MemoryGovernor
impl UnwindSafe for MemoryGovernor
Blanket Implementations§
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
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more