pub struct DiagnosticPulse { /* private fields */ }Expand description
Measures a library’s checkpoints without changing its signature.
Wrap the PulseTree you would pass to the library, pass &measured
instead, and finish the wrapper when the library returns:
use how_far_along::{Outcome, Phase, PulseTree, Total, Unstoppable};
use how_far_really::diagnostics::{DiagnosticPulse, Options};
use how_far_really::profile::{Profiler, StdClock};
let profiler = Profiler::new(StdClock::new(), 256);
let tree = PulseTree::new(Phase::new("encode", Total::Unknown), Unstoppable);
let measured = DiagnosticPulse::new(tree, &profiler);
let observer = measured.observer();
// let result = my_library::encode(&input, &measured);
measured.finish(Outcome::Succeeded)?;
let trace = profiler.snapshot().with_progress(observer.snapshot());
for finding in trace.diagnose(&Options::default()) {
eprintln!("{finding}");
}Every phase the library plans gets its own span, tied to its node in the
tree. A phase’s span starts at its first check or report; a stage of a
sequential split starts when the previous stage finished, and the first
stage when the plan was made. So time spent before a stage’s first
checkpoint is measured, and a stage that never checks at all still gets a
span. Workers that share one phase share its span; give each worker its
own Span when one worker’s long silence matters.
A phase that splits hands its time to its children: its own span ends at
the split, and a sequential stage then records a SpanKind::Wait span
while it coordinates them. A stage is thereby timed from entry to exit,
and its children’s work never counts as its own missing checkpoints.
Pulse::share returns an instrumented owned view, so checks made inside
code that owns its stop policy, such as a codec context, count toward the
stage that handed it out. may_stop and may_report are always true, so
libraries that skip calls on no-op pulses still make the calls measured.
Creating one turns on Profiler::set_report_timing.
Implementations§
Trait Implementations§
Source§impl Complete for DiagnosticPulse
impl Complete for DiagnosticPulse
Source§fn complete_as(self, outcome: Outcome)
fn complete_as(self, outcome: Outcome)
Source§fn complete<T, E>(self, result: Result<T, E>) -> Result<T, E>where
E: AsStopReason,
fn complete<T, E>(self, result: Result<T, E>) -> Result<T, E>where
E: AsStopReason,
AsStopReason, record completion, and return the
original result. Read moreSource§fn complete_classified<T, E>(
self,
result: Result<T, E>,
is_stop: impl FnOnce(&E) -> bool,
) -> Result<T, E>
fn complete_classified<T, E>( self, result: Result<T, E>, is_stop: impl FnOnce(&E) -> bool, ) -> Result<T, E>
AsStopReason.Source§fn complete_with<T, E>(
self,
body: impl FnOnce(&mut Self) -> Result<T, E>,
) -> Result<T, E>where
E: AsStopReason,
fn complete_with<T, E>(
self,
body: impl FnOnce(&mut Self) -> Result<T, E>,
) -> Result<T, E>where
E: AsStopReason,
body with this owner, then complete the owner with
the body’s result and return that result unchanged. Read moreSource§fn complete_with_classified<T, E>(
self,
is_stop: impl FnOnce(&E) -> bool,
body: impl FnOnce(&mut Self) -> Result<T, E>,
) -> Result<T, E>
fn complete_with_classified<T, E>( self, is_stop: impl FnOnce(&E) -> bool, body: impl FnOnce(&mut Self) -> Result<T, E>, ) -> Result<T, E>
complete_with with an explicit classifier, for
a foreign error type that cannot implement AsStopReason, such as an error
wrapped with its source location.