Skip to main content

MetricsSnapshot

Struct MetricsSnapshot 

Source
#[non_exhaustive]
pub struct MetricsSnapshot { pub turns: u64, pub depth_samples: u64, pub high_depth_mean: f64, pub high_depth_max: u64, pub low_depth_mean: f64, pub low_depth_max: u64, pub longest: Option<(CommandKind, Duration)>, pub low_starved_turns: u64, pub low_starved_run_max: u64, pub kinds: Vec<KindSnapshot>, }
Expand description

What the actor has done since the database was opened.

Fields (Non-exhaustive)§

This struct is marked as non-exhaustive
Non-exhaustive structs could have additional fields added in future. Therefore, non-exhaustive structs cannot be constructed in external crates using the traditional Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.
§turns: u64

Commands executed, i.e. the sum of KindSnapshot::turns. The two agree by construction rather than by coincidence.

§depth_samples: u64

Loop iterations that took a queue-depth reading. Always at least turns + 1 on a live actor, because the reading is taken on the way in to a select! that has not resolved yet. This is the denominator of the two means below, and it is exposed so the difference is visible rather than looking like drift.

§high_depth_mean: f64§high_depth_max: u64§low_depth_mean: f64§low_depth_max: u64§longest: Option<(CommandKind, Duration)>

The longest hold since open and what caused it. None before the first turn, and — honestly — also when every turn so far took under a microsecond, which on this path does not happen.

§low_starved_turns: u64

Turns spent on high-priority work while low-priority work was already queued (0.12.10, W4.4, D-153).

The actor’s select! is biased and has no floor, so this is the measurement of a bound the design has always had and never observed. On its own it is not alarming: a busy database should prefer interactive writes, and this counter rising is that working. Read it beside Self::low_starved_run_max, which is the number with teeth.

§low_starved_run_max: u64

The longest unbroken run of the above — i.e. the most turns any single low-priority command has waited (0.12.10, W4.4, D-153).

This is the one that answers “can low-priority work be starved”. A large low_starved_turns spread over a long session says the tiers are doing their job; a large run says one specific chunk, rebuild or archive sat behind that many interactive writes in a row.

§There is deliberately no forced-yield policy, and the reason changed

(0.13.26, W10.4, D-199)

It used to be “adding one now would be fixing a bound nobody has observed being hit”. That premise died twice. D-153 hit the bound completely on a synthetic burst, and W10.4 then hit it on an ordinary one: four closed-loop writers — each awaiting its own write before issuing the next, which is what application code does — starve the low tier for essentially all of their writes (examples/fairness_probe.rs). The run is bounded by how long the caller keeps offering interactive work, not by concurrency and not by anything in this crate.

What replaced it is the floor’s own price. “After N starved turns, take one low-priority command” cannot choose which command — the low queue is an mpsc channel and its head is not inspectable — and at least one low-priority kind is exempt from crate::CHUNK_BUDGET by contract: an crate::Database::archive was measured at 3.3 s unwindowed on an 8,000-key backlog. So the floor would add an unbounded term to the interactive worst case in order to unblock work that is declared not to be latency-sensitive, which is the tier split running backwards.

The lever that does work belongs to the caller: 1 ms of think time between a writer’s writes takes four writers from ~78 to ~2. Which makes this field the instrument for a decision the caller owns rather than a defect report about the actor.

§kinds: Vec<KindSnapshot>

Implementations§

Source§

impl MetricsSnapshot

Source

pub fn budget_violations(&self) -> Vec<&KindSnapshot>

Kinds that broke the budget, worst first. The one-line answer to “is the 3 ms bound holding?”.

Trait Implementations§

Source§

impl Clone for MetricsSnapshot

Source§

fn clone(&self) -> MetricsSnapshot

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for MetricsSnapshot

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl PartialEq for MetricsSnapshot

Source§

fn eq(&self, other: &MetricsSnapshot) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for MetricsSnapshot

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoRequest<T> for T

Source§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more