Skip to main content

wisp/renderer/
stats.rs

1use crate::view::syntax::HighlightStats;
2use std::time::Instant;
3
4/// Work one [`Renderer`](super::Renderer) did since the last
5/// [`Renderer::take_stats`](super::Renderer::take_stats), so tests can bound
6/// per-frame rendering work by counting it instead of timing it.
7///
8/// Byte counters measure input re-processed, not output produced: an item whose
9/// rendering is O(content) every frame shows up as its content size again and
10/// again, whatever the drawn output looks like.
11#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
12pub struct RenderStats {
13    pub frames: u64,
14    /// Item renders that ran rather than being served from a cache. A streaming
15    /// item rebuilds as its content grows and an open tool call as its spinner
16    /// moves; anything else rebuilding is wasted work.
17    pub item_rebuilds: u64,
18    pub markdown_bytes_parsed: u64,
19    pub markdown_bytes_scanned: u64,
20    pub markdown_prefix_bytes_copied: u64,
21    pub markdown_rows_generated: u64,
22    pub markdown_rows_materialized: u64,
23    /// Largest live region any single render produced. Native scrollback commits
24    /// are supposed to bound this to roughly the viewport height.
25    pub max_live_rows: usize,
26    pub history_rows_inserted: u64,
27    pub highlight: HighlightStats,
28    pub ns_layout: u64,
29    pub ns_live: u64,
30    pub ns_draw: u64,
31    pub ns_item_rebuild: u64,
32}
33
34/// One measured stretch of a draw. Compiled to nothing outside the `testing`
35/// feature, so production draws pay only the zero-sized struct.
36pub(super) struct Lap {
37    #[cfg(feature = "testing")]
38    start: Instant,
39}
40
41impl Lap {
42    pub(super) fn start() -> Self {
43        #[cfg(feature = "testing")]
44        return Self { start: Instant::now() };
45        #[cfg(not(feature = "testing"))]
46        Self {}
47    }
48
49    #[cfg_attr(not(feature = "testing"), expect(clippy::unused_self))]
50    pub(super) fn ns(self) -> u64 {
51        #[cfg(feature = "testing")]
52        return u64::try_from(self.start.elapsed().as_nanos()).unwrap_or(u64::MAX);
53        #[cfg(not(feature = "testing"))]
54        0
55    }
56}