Skip to main content

fret_ui/tree/debug/
frame_stats.rs

1use super::super::*;
2use fret_core::TimerToken;
3
4#[derive(Debug, Default, Clone, Copy)]
5pub struct UiDebugFrameStats {
6    pub frame_id: FrameId,
7    /// Approximate capacity retained by per-frame scratch (“frame arena”) containers.
8    ///
9    /// This is a coarse signal intended for diagnostics/triage: it tracks reserved capacity
10    /// (not current length) and intentionally underestimates hash table overhead.
11    pub frame_arena_capacity_estimate_bytes: u64,
12    /// Number of scratch containers that grew their capacity during the current frame.
13    ///
14    /// This is a proxy for allocator churn in hot paths that should ideally stabilize after
15    /// warmup.
16    pub frame_arena_grow_events: u32,
17    /// Number of child-element vectors reused from the per-window pool during element build.
18    ///
19    /// This is a proxy for “element tree arena” progress: higher reuse implies less allocator churn
20    /// while building the ephemeral declarative element tree.
21    pub element_children_vec_pool_reuses: u32,
22    /// Number of child-element vectors that had to be newly allocated during element build.
23    pub element_children_vec_pool_misses: u32,
24    /// Total time spent in event dispatch during the current frame.
25    ///
26    /// This includes pointer routing, capture/focus arbitration, and widget event hooks. It does
27    /// not include layout/prepaint/paint, which are tracked separately.
28    pub dispatch_time: Duration,
29    /// Number of pointer/drag events dispatched during the current frame.
30    pub dispatch_pointer_events: u32,
31    /// Total wall time spent dispatching pointer/drag events during the current frame.
32    pub dispatch_pointer_event_time: Duration,
33    /// Number of timer events dispatched during the current frame.
34    pub dispatch_timer_events: u32,
35    /// Total wall time spent dispatching timer events during the current frame.
36    pub dispatch_timer_event_time: Duration,
37    /// Number of timer events that resolved to an explicit element target.
38    pub dispatch_timer_targeted_events: u32,
39    /// Wall time spent dispatching explicitly targeted timer events.
40    pub dispatch_timer_targeted_time: Duration,
41    /// Number of timer events that fell back to broadcast delivery (no element target).
42    pub dispatch_timer_broadcast_events: u32,
43    /// Wall time spent in broadcast timer delivery (including layer scanning + dispatch).
44    pub dispatch_timer_broadcast_time: Duration,
45    /// Total number of layers visited during broadcast timer delivery.
46    pub dispatch_timer_broadcast_layers_visited: u32,
47    /// Time spent rebuilding the visible-layers scratch list for broadcast timer delivery.
48    pub dispatch_timer_broadcast_rebuild_visible_layers_time: Duration,
49    /// Time spent iterating candidate layers and dispatching broadcast timers.
50    pub dispatch_timer_broadcast_loop_time: Duration,
51    /// Slowest single timer event routing time observed in the current frame.
52    pub dispatch_timer_slowest_event_time: Duration,
53    /// Token of the slowest timer event observed in the current frame (if any).
54    pub dispatch_timer_slowest_token: Option<TimerToken>,
55    /// Whether the slowest timer event used the broadcast fallback.
56    pub dispatch_timer_slowest_was_broadcast: bool,
57    /// Number of non-pointer, non-timer events dispatched during the current frame.
58    pub dispatch_other_events: u32,
59    /// Total wall time spent dispatching non-pointer, non-timer events during the current frame.
60    pub dispatch_other_event_time: Duration,
61    /// Time spent inside hit-testing during the current frame (subset of `dispatch_time`).
62    pub hit_test_time: Duration,
63    /// Number of events dispatched during the current frame.
64    pub dispatch_events: u32,
65    /// Number of hit-test queries executed during the current frame.
66    pub hit_test_queries: u32,
67    /// Count of bounds-tree queries attempted during hit testing.
68    pub hit_test_bounds_tree_queries: u32,
69    /// Bounds-tree queries that were disabled (e.g. env-gated, layer not indexed, or unsupported transforms).
70    pub hit_test_bounds_tree_disabled: u32,
71    /// Bounds-tree queries that missed (no containing leaf).
72    pub hit_test_bounds_tree_misses: u32,
73    /// Bounds-tree queries that returned a candidate leaf.
74    pub hit_test_bounds_tree_hits: u32,
75    /// Bounds-tree candidates rejected by `hit_test_node_self_only`, forcing a fallback traversal.
76    pub hit_test_bounds_tree_candidate_rejected: u32,
77    /// Total bounds-tree nodes visited across all queries in the current frame.
78    pub hit_test_bounds_tree_nodes_visited: u32,
79    /// Total bounds-tree nodes pushed to the search stack across all queries in the current frame.
80    pub hit_test_bounds_tree_nodes_pushed: u32,
81    /// Number of hit-test queries that reused the cached path (no bounds-tree query needed).
82    pub hit_test_path_cache_hits: u32,
83    /// Number of hit-test queries that fell back to bounds-tree or full traversal (cache miss).
84    pub hit_test_path_cache_misses: u32,
85    /// Total wall time spent attempting the cached-path hit-test fast path in the current frame.
86    pub hit_test_cached_path_time: Duration,
87    /// Total wall time spent querying the bounds-tree index in the current frame.
88    pub hit_test_bounds_tree_query_time: Duration,
89    /// Total wall time spent validating bounds-tree candidates (`hit_test_node_self_only`) in the current frame.
90    pub hit_test_candidate_self_only_time: Duration,
91    /// Total wall time spent in full traversal fallback hit-testing in the current frame.
92    pub hit_test_fallback_traversal_time: Duration,
93    /// Total wall time spent updating hover state from pointer hit-testing in the current frame.
94    pub dispatch_hover_update_time: Duration,
95    /// Total wall time spent applying scroll-handle binding invalidations during event dispatch.
96    pub dispatch_scroll_handle_invalidation_time: Duration,
97    /// Total wall time spent computing active input layers and enforcing modal barrier scope.
98    pub dispatch_active_layers_time: Duration,
99    /// Total wall time spent constructing and publishing the window input context snapshot.
100    pub dispatch_input_context_time: Duration,
101    /// Total wall time spent building the event chain during dispatch.
102    pub dispatch_event_chain_build_time: Duration,
103    /// Total wall time spent delivering capture-phase widget events during dispatch.
104    pub dispatch_widget_capture_time: Duration,
105    /// Total wall time spent delivering bubble-phase widget events during dispatch.
106    pub dispatch_widget_bubble_time: Duration,
107    /// Total wall time spent computing the cursor icon from the pointer hit during dispatch.
108    pub dispatch_cursor_query_time: Duration,
109    /// Total wall time spent dispatching pointer-move layer observers (both post-dispatch and when
110    /// pointer dispatch is suppressed).
111    pub dispatch_pointer_move_layer_observers_time: Duration,
112    /// Total wall time spent dispatching the synthetic hover-move observer chain when the pointer crosses targets.
113    pub dispatch_synth_hover_observer_time: Duration,
114    /// Total wall time spent pushing cursor-icon effects during dispatch.
115    pub dispatch_cursor_effect_time: Duration,
116    /// Total wall time spent publishing post-dispatch window integration snapshots (input context,
117    /// command availability) during dispatch.
118    pub dispatch_post_dispatch_snapshot_time: Duration,
119    pub layout_time: Duration,
120    pub layout_collect_roots_time: Duration,
121    pub layout_invalidate_scroll_handle_bindings_time: Duration,
122    pub layout_expand_view_cache_invalidations_time: Duration,
123    pub layout_request_build_roots_time: Duration,
124    pub layout_pending_barrier_relayouts_time: Duration,
125    pub layout_repair_view_cache_bounds_time: Duration,
126    pub layout_contained_view_cache_roots_time: Duration,
127    pub layout_collapse_layout_observations_time: Duration,
128    /// Total wall time spent recording layout observations (`observed_in_layout` + globals).
129    pub layout_observation_record_time: Duration,
130    /// Total observed-model edges recorded into `observed_in_layout` during this frame.
131    pub layout_observation_record_models_items: u32,
132    /// Total observed-global edges recorded into `observed_globals_in_layout` during this frame.
133    pub layout_observation_record_globals_items: u32,
134    pub layout_prepaint_after_layout_time: Duration,
135    pub layout_skipped_engine_frame: bool,
136    pub layout_roots_time: Duration,
137    pub layout_barrier_relayouts_time: Duration,
138    pub layout_view_cache_time: Duration,
139    pub layout_semantics_refresh_time: Duration,
140    pub layout_focus_repair_time: Duration,
141    pub layout_deferred_cleanup_time: Duration,
142    pub prepaint_time: Duration,
143    pub paint_time: Duration,
144    pub paint_record_visual_bounds_time: Duration,
145    pub paint_record_visual_bounds_calls: u32,
146    /// Total wall time spent computing paint-cache keys and paint-cache enablement checks.
147    pub paint_cache_key_time: Duration,
148    /// Total wall time spent checking paint-cache hit eligibility (excluding replay itself).
149    pub paint_cache_hit_check_time: Duration,
150    /// Total wall time spent executing `Widget::paint()` (including push/pop transforms).
151    pub paint_widget_time: Duration,
152    /// Total wall time spent recording paint observations (`observed_in_paint` + globals).
153    pub paint_observation_record_time: Duration,
154    /// Total wall time spent iterating element-runtime observed models inside `ElementHostWidget::paint_impl`.
155    pub paint_host_widget_observed_models_time: Duration,
156    /// Total observed-model edges iterated inside `ElementHostWidget::paint_impl`.
157    pub paint_host_widget_observed_models_items: u32,
158    /// Total wall time spent iterating element-runtime observed globals inside `ElementHostWidget::paint_impl`.
159    pub paint_host_widget_observed_globals_time: Duration,
160    /// Total observed-global edges iterated inside `ElementHostWidget::paint_impl`.
161    pub paint_host_widget_observed_globals_items: u32,
162    /// Total wall time spent resolving the element instance (`ElementInstance`) inside `ElementHostWidget::paint_impl`.
163    pub paint_host_widget_instance_lookup_time: Duration,
164    /// Number of `ElementInstance` lookups performed inside `ElementHostWidget::paint_impl`.
165    pub paint_host_widget_instance_lookup_calls: u32,
166    /// Total wall time spent preparing text blobs (`TextSystem::prepare`) during `Widget::paint`.
167    pub paint_text_prepare_time: Duration,
168    /// Number of text blob preparations performed during `Widget::paint`.
169    pub paint_text_prepare_calls: u32,
170    /// Count of text prepares where the cached blob was missing.
171    pub paint_text_prepare_reason_blob_missing: u32,
172    /// Count of text prepares triggered by a scale factor change.
173    pub paint_text_prepare_reason_scale_changed: u32,
174    /// Count of text prepares triggered by a plain-text change.
175    pub paint_text_prepare_reason_text_changed: u32,
176    /// Count of text prepares triggered by an attributed-text change.
177    pub paint_text_prepare_reason_rich_changed: u32,
178    /// Count of text prepares triggered by a text-style change.
179    pub paint_text_prepare_reason_style_changed: u32,
180    /// Count of text prepares triggered by a wrap-mode change.
181    pub paint_text_prepare_reason_wrap_changed: u32,
182    /// Count of text prepares triggered by an overflow-mode change.
183    pub paint_text_prepare_reason_overflow_changed: u32,
184    /// Count of text prepares triggered by a max-width change.
185    pub paint_text_prepare_reason_width_changed: u32,
186    /// Count of text prepares triggered by a font-stack-key change.
187    pub paint_text_prepare_reason_font_stack_changed: u32,
188    pub paint_input_context_time: Duration,
189    pub paint_scroll_handle_invalidation_time: Duration,
190    pub paint_collect_roots_time: Duration,
191    pub paint_publish_text_input_snapshot_time: Duration,
192    pub paint_collapse_observations_time: Duration,
193    pub layout_nodes_visited: u32,
194    pub layout_nodes_performed: u32,
195    pub prepaint_nodes_visited: u32,
196    pub paint_nodes: u32,
197    pub paint_nodes_performed: u32,
198    pub paint_cache_hits: u32,
199    pub paint_cache_misses: u32,
200    pub paint_cache_replayed_ops: u32,
201    /// Paint-cache replay attempts that were allowed specifically by the
202    /// `FRET_UI_PAINT_CACHE_ALLOW_HIT_TEST_ONLY` gate.
203    pub paint_cache_hit_test_only_replay_allowed: u32,
204    /// Hit-test-only replay attempts rejected because the previous cache key did not match.
205    pub paint_cache_hit_test_only_replay_rejected_key_mismatch: u32,
206    pub paint_cache_replay_time: Duration,
207    pub paint_cache_bounds_translate_time: Duration,
208    pub paint_cache_bounds_translated_nodes: u32,
209    pub interaction_cache_hits: u32,
210    pub interaction_cache_misses: u32,
211    pub interaction_cache_replayed_records: u32,
212    pub interaction_records: u32,
213    /// Number of layout engine root solves performed during the current frame.
214    pub layout_engine_solves: u64,
215    /// Total time spent in layout engine solves during the current frame.
216    pub layout_engine_solve_time: Duration,
217    /// Total number of `layout_engine_child_local_rect` queries performed during the current frame.
218    pub layout_engine_child_rect_queries: u64,
219    /// Total wall time spent inside layout engine child-rect queries during the current frame.
220    pub layout_engine_child_rect_time: Duration,
221    /// Number of "widget-local" layout engine solves triggered as a fallback when a widget cannot
222    /// consume already-solved engine child rects.
223    ///
224    /// The goal for v2 is to keep this at `0` for normal UI trees by ensuring explicit layout
225    /// barriers (scroll/virtualization/splits/...) register viewport roots or explicitly solve
226    /// their child roots.
227    pub layout_engine_widget_fallback_solves: u64,
228    pub layout_fast_path_taken: bool,
229    pub layout_invalidations_count: u32,
230    pub layout_subtree_dirty_agg_enabled: bool,
231    /// Number of aggregation update operations performed during the current frame.
232    pub layout_subtree_dirty_agg_updates: u32,
233    /// Total number of nodes whose aggregation counter was updated during the current frame.
234    pub layout_subtree_dirty_agg_nodes_touched: u32,
235    /// Max parent-walk length observed in a single aggregation update during the current frame.
236    pub layout_subtree_dirty_agg_max_parent_walk: u32,
237    /// Total nodes processed by subtree rebuilds during the current frame.
238    pub layout_subtree_dirty_agg_rebuild_nodes: u32,
239    /// Count of validation failures observed during the current frame.
240    pub layout_subtree_dirty_agg_validation_failures: u32,
241    /// Unique nodes observed as invalidation roots for model changes during the current frame.
242    pub model_change_invalidation_roots: u32,
243    /// Count of changed models consumed for propagation during the current frame.
244    pub model_change_models: u32,
245    /// Total (model -> node) observation edges scanned during propagation.
246    pub model_change_observation_edges: u32,
247    /// Count of changed models with no observation edges.
248    pub model_change_unobserved_models: u32,
249    /// Unique nodes observed as invalidation roots for global changes during the current frame.
250    pub global_change_invalidation_roots: u32,
251    /// Count of changed globals consumed for propagation during the current frame.
252    pub global_change_globals: u32,
253    /// Total (global -> node) observation edges scanned during propagation.
254    pub global_change_observation_edges: u32,
255    /// Count of changed globals with no observation edges.
256    pub global_change_unobserved_globals: u32,
257    /// Total nodes visited across invalidation walks during the current frame.
258    pub invalidation_walk_nodes: u32,
259    /// Total invalidation walks performed during the current frame.
260    pub invalidation_walk_calls: u32,
261    /// Nodes visited across invalidation walks attributed to model changes.
262    pub invalidation_walk_nodes_model_change: u32,
263    /// Invalidation walks attributed to model changes.
264    pub invalidation_walk_calls_model_change: u32,
265    /// Nodes visited across invalidation walks attributed to global changes.
266    pub invalidation_walk_nodes_global_change: u32,
267    /// Invalidation walks attributed to global changes.
268    pub invalidation_walk_calls_global_change: u32,
269    /// Nodes visited across invalidation walks attributed to hover state changes.
270    pub invalidation_walk_nodes_hover: u32,
271    /// Invalidation walks attributed to hover state changes.
272    pub invalidation_walk_calls_hover: u32,
273    /// Nodes visited across invalidation walks attributed to focus changes.
274    pub invalidation_walk_nodes_focus: u32,
275    /// Invalidation walks attributed to focus changes.
276    pub invalidation_walk_calls_focus: u32,
277    /// Nodes visited across invalidation walks attributed to all other sources.
278    pub invalidation_walk_nodes_other: u32,
279    /// Invalidation walks attributed to all other sources.
280    pub invalidation_walk_calls_other: u32,
281    /// Count of hover target changes for `Pressable` instances during the current frame.
282    pub hover_pressable_target_changes: u32,
283    /// Count of hover target changes for `HoverRegion` instances during the current frame.
284    pub hover_hover_region_target_changes: u32,
285    /// Count of declarative instance changes that happened in a frame that also observed a hover
286    /// target change.
287    pub hover_declarative_instance_changes: u32,
288    /// Count of declarative `HitTest` invalidations attributed to hover during the current frame.
289    pub hover_declarative_hit_test_invalidations: u32,
290    /// Count of declarative `Layout` invalidations attributed to hover during the current frame.
291    pub hover_declarative_layout_invalidations: u32,
292    /// Count of declarative `Paint` invalidations attributed to hover during the current frame.
293    pub hover_declarative_paint_invalidations: u32,
294    /// Whether view-cache mode is active for this frame.
295    pub view_cache_active: bool,
296    /// How many invalidation walks were truncated by a view-cache boundary.
297    pub view_cache_invalidation_truncations: u32,
298    /// How many "contained" view-cache roots were re-laid out during the final pass.
299    pub view_cache_contained_relayouts: u32,
300    /// How many view-cache roots were observed during the current frame.
301    pub view_cache_roots_total: u32,
302    /// How many view-cache roots were reused during the current frame.
303    pub view_cache_roots_reused: u32,
304    /// View-cache roots that were not reused because they were mounted for the first time.
305    pub view_cache_roots_first_mount: u32,
306    /// View-cache roots that were not reused because their backing `NodeId` was recreated.
307    pub view_cache_roots_node_recreated: u32,
308    /// View-cache roots that were not reused because the declarative cache key did not match.
309    pub view_cache_roots_cache_key_mismatch: u32,
310    /// View-cache roots that were not reused because they were not marked as reuse roots.
311    ///
312    /// This is an authoring-level signal: either view-cache was not enabled, or reuse was gated off
313    /// by local state (e.g. `view_cache_needs_rerender` / layout invalidation) upstream.
314    pub view_cache_roots_not_marked_reuse_root: u32,
315    /// View-cache roots that were not reused because `view_cache_needs_rerender` was set.
316    pub view_cache_roots_needs_rerender: u32,
317    /// View-cache roots that were not reused because they had a layout invalidation.
318    pub view_cache_roots_layout_invalidated: u32,
319    /// View-cache roots recorded from retained/manual cache roots (non-declarative).
320    pub view_cache_roots_manual: u32,
321    /// How many times `set_children_barrier` was applied (structural changes without forcing
322    /// ancestor relayout).
323    pub set_children_barrier_writes: u32,
324    /// How many barrier relayout roots were scheduled via `set_children_barrier` in this frame.
325    pub barrier_relayouts_scheduled: u32,
326    /// How many barrier relayout roots were actually laid out in this frame.
327    pub barrier_relayouts_performed: u32,
328    /// How many VirtualList visible-range checks were evaluated (used to request rerenders under
329    /// view-cache reuse).
330    pub virtual_list_visible_range_checks: u32,
331    /// How many VirtualList visible-range checks requested a refresh (range delta outside the
332    /// currently mounted span).
333    pub virtual_list_visible_range_refreshes: u32,
334    /// How many VirtualList window shifts were observed during the current frame.
335    pub virtual_list_window_shifts_total: u32,
336    /// How many VirtualList window shifts required a non-retained cache-root rerender.
337    pub virtual_list_window_shifts_non_retained: u32,
338    /// How many retained VirtualList hosts were reconciled (attach/detach without rerendering the
339    /// parent view-cache root).
340    pub retained_virtual_list_reconciles: u32,
341    /// Total items attached across retained VirtualList reconciles (new keys mounted).
342    pub retained_virtual_list_attached_items: u32,
343    /// Total items detached across retained VirtualList reconciles (keys removed from children).
344    pub retained_virtual_list_detached_items: u32,
345    pub focus: Option<NodeId>,
346    pub captured: Option<NodeId>,
347}