Skip to main content

FlushStats

Struct FlushStats 

Source
#[non_exhaustive]
pub struct FlushStats {
Show 19 fields pub root_writes: u32, pub writes_suppressed: u32, pub nodes_marked_check: u32, pub nodes_marked_dirty: u32, pub max_propagation_depth: u32, pub effects_queued: u32, pub effects_coalesced: u32, pub effects_run: u32, pub effects_skipped: u32, pub effects_disposed: u32, pub effects_pending: u32, pub computed_verified: u32, pub computed_recomputed: u32, pub computed_changed: u32, pub computed_suppressed: u32, pub edges_added: u32, pub edges_removed: u32, pub jobs_at_start: u32, pub jobs_at_finish: u32,
}
Expand description

What one flush did.

Delivered on DiagnosticEvent::FlushFinished. An idle window’s flush should be all zeroes, and that is the point: without this, “a flush happened” and “a flush did work” are indistinguishable, and an idle application’s cost is a CPU percentage rather than a number.

§Availability

Unlike GraphStats, these counters are maintained only while a diagnostic subscription is active. The distinction is not arbitrary: GraphStats backs a query that can be called at any moment, so it must always be true, whereas FlushStats is only ever observed by being delivered in an event, and an event nobody subscribed to is not delivered. Counters that back a query are always maintained; counters that back an event follow the event.

§Attribution

Work is attributed to the next flush that closes, and counted exactly once.

  • Work performed during a flush belongs to the innermost flush open at the time. Flushes nest — a re-entrant Reactor::flush_now from inside a job opens a genuine inner epoch — and an inner flush’s totals are not rolled up into the enclosing one, so summing the flushes in a capture double-counts nothing.
  • Work performed outside any flush — most importantly the writes that scheduled it — is handed to the flush that drains it. A write and the effect run it causes therefore appear in the same totals, which is what makes root_writes answer “what set this flush off”. The corollary: work never followed by a flush is never reported. Disposing an effect and then stopping, for example, accumulates a disposal that no flush arrives to carry. That is deliberate — a drain with an empty queue is not a flush, and making one happen because diagnostics are subscribed would break the rule that subscribing never changes behaviour. In an application, where flushes keep coming, it is invisible.

§A settled graph does not flush

A drain with nothing to drain is not a flush: it opens no epoch and reports nothing. So the signature of an idle application is no flushes at all, not a stream of empty ones. An empty FlushStats still occurs for a boundary a consumer declared with Reactor::external_flush, which is reported whether or not the drain found work — see examples/idle_audit.rs.

§No durations

Adaptite reads no clock. Every field here is a count. A consumer that wants a duration timestamps the FlushStarted/FlushFinished pair itself.

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.
§root_writes: u32

Writes and explicit triggers on source nodes that reached the graph.

§writes_suppressed: u32

Writes discarded by a source’s own equality check before reaching the graph.

Work that happened and produced nothing. root_writes + writes_suppressed is how often something tried to write; root_writes alone is how often it mattered. A large ratio between them is a producer running more often than it needs to, which is invisible from the propagation side because a suppressed write propagates nothing by definition.

§nodes_marked_check: u32

Marks delivered to observers saying a computed input may have changed.

§nodes_marked_dirty: u32

Marks delivered to observers saying a direct dependency definitely changed.

§max_propagation_depth: u32

Deepest chain of marking walked in one propagation.

One write reaching an effect directly is depth 1; through two memos, depth 3.

§effects_queued: u32

Effects that acquired a pending run.

§effects_coalesced: u32

Invalidations absorbed by an effect that already had a run pending.

§effects_run: u32

Effect bodies executed.

§effects_skipped: u32

Effects whose verification proved their inputs unchanged, so the body was skipped.

§effects_disposed: u32

Effects disposed.

§effects_pending: u32

Effects still holding a pending run when the flush closed.

§computed_verified: u32

Check-marked computed nodes that verified their inputs.

§computed_recomputed: u32

Computations that ran.

computed_changed + computed_suppressed is at most this, not equal to it: a computation that unwound published nothing and is neither. The difference is the number that failed.

§computed_changed: u32

Computations that published a new value.

§computed_suppressed: u32

Computations whose comparator judged the value unchanged, sparing everything downstream.

§edges_added: u32

Dependency edges recorded.

§edges_removed: u32

Dependency edges retracted.

§jobs_at_start: u32

Jobs queued when the flush opened.

§jobs_at_finish: u32

Jobs still queued when the flush closed.

Non-zero after a panicking job: the flush hands what is left to a fresh one.

Implementations§

Source§

impl FlushStats

Source

pub fn is_empty(&self) -> bool

Returns true when the flush did no reactive work at all.

A settled graph does not flush at all, so an idle application usually asserts that no flush arrived. This is for the flush an Reactor::external_flush reports over a settled graph — the boundary was declared, but there was nothing to do.

Deliberately ignores jobs_at_start, jobs_at_finish and effects_pending, which describe outstanding state rather than work this flush did. An empty flush with a non-zero effects_pending is a real and meaningful combination: nothing happened here, and an effect is still sitting unrun in a consumer-owned lane.

Trait Implementations§

Source§

impl Clone for FlushStats

Source§

fn clone(&self) -> Self

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 Copy for FlushStats

Source§

impl Debug for FlushStats

Source§

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

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

impl Default for FlushStats

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl Eq for FlushStats

Source§

impl PartialEq for FlushStats

Source§

fn eq(&self, other: &Self) -> 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 FlushStats

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<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<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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> 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, !>

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<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