Skip to main content

FrameStats

Struct FrameStats 

Source
pub struct FrameStats { /* private fields */ }
Expand description

Per-shell frame-timing recorder: a ring buffer of the last RING_CAPACITY frames’ FramePasses plus lifetime running counters, aggregated on demand by FrameStats::summary and rate-limit logged by FrameStats::should_emit/FrameStats::emit_log.

The Android, iOS, and desktop shells each construct one of these — a standalone, host-testable recorder.

Implementations§

Source§

impl FrameStats

Source

pub fn new() -> Self

A recorder honoring the process-wide enabled/raw_enabled switches — what every shell constructs.

Source

pub fn new_enabled(is_enabled: bool) -> Self

Test/advanced seam: construct with an explicit enabled flag, bypassing enabled’s cache. Every shell should prefer Self::new; this exists so tests can exercise both the enabled and disabled paths deterministically in the same process (enabled()’s OnceLock can only ever resolve once per process). Raw-export mode is left off; use Self::with_capacity_enabled_and_raw to exercise it.

Source

pub fn with_capacity_enabled(capacity: usize, is_enabled: bool) -> Self

Test seam: a smaller ring capacity, so eviction behavior is exercisable without pushing RING_CAPACITY frames. Raw-export mode is left off; use Self::with_capacity_enabled_and_raw to exercise it.

Source

pub fn with_capacity_enabled_and_raw( capacity: usize, is_enabled: bool, is_raw: bool, ) -> Self

Test/advanced seam: construct with explicit enabled and raw-export flags, bypassing both enabled’s and raw_enabled’s caches (see Self::new_enabled’s docs for why a test needs to bypass the cache). is_raw only takes effect when is_enabled is also true — the same two-dial contract Self::new applies to the real FRUST_TRACE/FRUST_TRACE_RAW switches.

Source

pub fn record(&mut self, passes: FramePasses)

Record one frame’s pass durations. A cheap no-op (no allocation, no clock read — the caller already measured passes) when disabled. When raw-export mode is on (see raw_enabled), additionally formats and logs one frust-perf raw line for this frame — a skipped frame (passes.skipped) still gets a line (all-zero pass durations, skipped=1) so a harness can compute honest frame pacing across the mobile frame gate.

This is also the single point where a benchmark scenario marker is emitted: every marker this frame carries — staged on this thread by the scene handoff, or raised on this thread when there is no render thread — is logged, in the order it was raised, stamped with this frame’s n and immediately ahead of this frame’s own frust-perf raw line, so a marker’s frame number names the recorded frame that actually carried it, not a guess made on whichever thread raised it (see mark_scenario_start).

Source

pub fn total_frames(&self) -> u64

Total frames ever recorded (including skipped), regardless of the ring-buffer window.

Source

pub fn summary(&self) -> FrameSummary

Aggregate the current ring-buffer window plus the lifetime running counters into a FrameSummary.

Percentile semantics: nearest-rank, computed over only the non-skipped frames currently in the ring buffer (a skipped frame’s all-zero pass durations would otherwise silently pull percentiles down and misrepresent real frame cost) — for a sorted-ascending sample of n values, the p-th percentile is the value at 1-indexed rank ceil(p * n / 100), computed with integer ceiling division ((p * n).div_ceil(100)) and clamped to [1, n], so no floating-point rounding is involved. An empty (or all-skipped) window reports Duration::ZERO for every percentile field.

Source

pub fn should_emit(&self) -> bool

Whether at least [EMIT_INTERVAL] of frame time has accumulated since the last Self::emit_log (or construction) — the “one line every ~2s of frames” rate limit. Always false when disabled.

Source

pub fn emit_log(&mut self)

Emit one structured frust-perf frame ... line via log::info! and reset the Self::should_emit accumulator. A no-op when disabled. A shell calls this only when Self::should_emit is true (it does not check it itself, so a test can force an emission regardless of accumulated time).

Trait Implementations§

Source§

impl Debug for FrameStats

Source§

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

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

impl Default for FrameStats

Source§

fn default() -> Self

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

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> ErasedDestructor for T
where T: 'static,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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> StorageAccess<T> for T

Source§

fn as_borrowed(&self) -> &T

Borrows the value.
Source§

fn into_taken(self) -> T

Takes the value.
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.