kui_trace/record.rs
1//! The records a recording is made of (ADR 0058, decision 2): each placed
2//! on one clock — µs since the recording began — and, where it says, on a
3//! track. Frames are intervals on that clock, not its unit: what happens
4//! after one frame ends and before the next begins is that next frame's
5//! gap.
6//!
7//! No record holds a payload, typed text or a concealed field's
8//! anything: kinds, keys, labels and times. A recording goes into bug
9//! reports.
10
11/// A string written once per recording by a [`Record::Name`]; `0` is the
12/// empty string, never written.
13pub type NameId = u32;
14
15/// A row of the timeline: [`Track::MAIN`] the thread the core runs on,
16/// [`Track::LOOP`] the driver's loop, and one per name `perf_measure` was
17/// given, declared by a [`Record::Track`].
18#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
19pub struct Track(pub u32);
20
21impl Track {
22 pub const MAIN: Track = Track(0);
23 pub const LOOP: Track = Track(1);
24}
25
26/// Who a span or a measurement is for.
27#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
28pub enum Origin {
29 /// kui's own: `build`, `layout`, `emit`, the devtools, a fill.
30 Kui,
31 /// The app.
32 Host,
33 /// An extension, by its namespace.
34 Extension(NameId),
35}
36
37/// What the recording was made of, once, first.
38#[derive(Clone, Debug, Default, PartialEq)]
39pub struct Session {
40 /// The kui version that wrote it.
41 pub kui: String,
42 /// The app's name, as its window titled it.
43 pub app: String,
44 /// `macos`, `windows`, `linux`, …
45 pub platform: String,
46 /// The display's refresh rate, and the frame budget it makes.
47 pub refresh_hz: f32,
48 pub budget_ms: f32,
49 pub scale: f32,
50 /// The wall clock at 0, ms since the Unix epoch.
51 pub wall_ms: u64,
52}
53
54/// A span closed: a name, a start and a length on its track, nested in
55/// its parent.
56#[derive(Clone, Debug, PartialEq)]
57pub struct Span {
58 pub track: Track,
59 /// Unique in the recording; `0` is no span.
60 pub id: u32,
61 /// The span it was opened inside, or `0`.
62 pub parent: u32,
63 pub name: NameId,
64 pub origin: Origin,
65 pub start: u64,
66 pub dur: u64,
67 /// The thread's time on a CPU over it, where the platform reads one.
68 pub cpu: Option<u64>,
69 /// The key of the node the builder had open as it began, or `0`.
70 pub node: u64,
71 /// Left open when its frame ended, and closed there.
72 pub cut: bool,
73}
74
75impl Span {
76 pub fn end(&self) -> u64 {
77 self.start.saturating_add(self.dur)
78 }
79}
80
81/// What the driver's loop did.
82#[derive(Clone, Copy, Debug, PartialEq)]
83pub enum LoopEvent {
84 /// Went to sleep, until a time when there was one.
85 Sleep { until: Option<u64> },
86 /// Woke, and why (`input`, `wake`, `timer`, `redraw`, …).
87 Woke { by: NameId },
88 /// Handled an OS event that never became input.
89 Os { kind: NameId },
90}
91
92/// One record.
93#[derive(Clone, Debug, PartialEq)]
94pub enum Record {
95 Session(Session),
96 Name {
97 id: NameId,
98 text: String,
99 },
100 Track {
101 id: Track,
102 name: NameId,
103 },
104 /// A frame begun, with why it runs: the cause kinds and the named
105 /// ones (`wake: parser`, `request: caret blink`).
106 FrameBegin {
107 t: u64,
108 frame: u64,
109 causes: Vec<NameId>,
110 },
111 /// Who held the frame the last one left owed: what for and its name.
112 Holder {
113 frame: u64,
114 what: NameId,
115 name: NameId,
116 node: u64,
117 },
118 /// A frame finished: whether it drew what the one before drew, and
119 /// how many nodes it held.
120 FrameEnd {
121 t: u64,
122 frame: u64,
123 unchanged: Option<bool>,
124 nodes: u32,
125 },
126 /// A frame drawn: the driver's render and vsync's wait, µs.
127 Present {
128 t: u64,
129 frame: u64,
130 render: u64,
131 wait: u64,
132 },
133 Span(Span),
134 /// Input arriving: its kind and, for a run of one kind (pointer
135 /// moves), how many and until when — never before `t`, which is what
136 /// a single input's `until` is.
137 Input {
138 t: u64,
139 kind: NameId,
140 os_t: Option<u64>,
141 count: u32,
142 until: u64,
143 },
144 /// An event handed to the app: its kind and its node.
145 Event {
146 t: u64,
147 kind: NameId,
148 node: u64,
149 },
150 Wake {
151 t: u64,
152 name: NameId,
153 },
154 /// A frame asked for: why, and the source line that asked.
155 Request {
156 t: u64,
157 why: NameId,
158 at: NameId,
159 },
160 Loop {
161 t: u64,
162 event: LoopEvent,
163 },
164 /// A frame's counter: its total over the frame.
165 Counter {
166 t: u64,
167 frame: u64,
168 name: NameId,
169 value: i64,
170 },
171 /// A reading set.
172 Gauge {
173 t: u64,
174 name: NameId,
175 value: f64,
176 },
177 /// An instant.
178 Mark {
179 t: u64,
180 track: Track,
181 name: NameId,
182 },
183 /// A line the app wrote (`perf_note`): what the numbers beside it
184 /// cannot say — a pane's "editor moved, reads fs.stat".
185 Note {
186 t: u64,
187 text: String,
188 },
189 /// A component placed (ADR 0067): its kind, the node it is at, how
190 /// it was filled — `replayed`, or drawn fresh and why in a word
191 /// (`not-kept`, `params`, `reads`, `not-replayable`, `heard`) — and,
192 /// for `reads` and `not-replayable`, the fact that moved or what made
193 /// it unreplayable: `hover 00000000000000ab`, `the clock`. The fact's
194 /// kind and node, never what it read.
195 Placement {
196 t: u64,
197 node: u64,
198 component: NameId,
199 answer: NameId,
200 why: NameId,
201 },
202}
203
204impl Record {
205 /// The time it is placed at, for one that has one.
206 pub fn t(&self) -> Option<u64> {
207 Some(match self {
208 Record::Session(_)
209 | Record::Name { .. }
210 | Record::Track { .. }
211 | Record::Holder { .. } => return None,
212 Record::FrameBegin { t, .. }
213 | Record::FrameEnd { t, .. }
214 | Record::Present { t, .. }
215 | Record::Input { t, .. }
216 | Record::Event { t, .. }
217 | Record::Wake { t, .. }
218 | Record::Request { t, .. }
219 | Record::Loop { t, .. }
220 | Record::Counter { t, .. }
221 | Record::Gauge { t, .. }
222 | Record::Mark { t, .. }
223 | Record::Note { t, .. }
224 | Record::Placement { t, .. } => *t,
225 Record::Span(s) => s.start,
226 })
227 }
228}