#[cfg(feature = "devtools")]
use std::rc::Rc;
#[cfg(feature = "devtools")]
use web_time::Instant;
use crate::core::component::Component;
use super::{AppRunner, DrawMode};
#[cfg(feature = "devtools")]
fn dirty_level_label(draw_mode: DrawMode) -> &'static str {
match draw_mode {
DrawMode::Full => "full",
DrawMode::LayoutOnly => "layout",
DrawMode::PaintOnly => "paint",
}
}
impl<C: Component> AppRunner<C> {
#[cfg(feature = "devtools")]
pub(crate) fn record_devtools_frame_metrics(
&mut self,
draw_mode: DrawMode,
total_duration: std::time::Duration,
reconcile_duration: std::time::Duration,
draw_duration: std::time::Duration,
) {
if self.devtools_metrics_suppressed {
return;
}
if !self.devtools_config.metrics {
return;
}
if !self.devtools_state.borrow().visible {
return;
}
let (memo_hits, memo_misses) = crate::core::nested::take_memo_counters();
let mut node_count = self.core.tree.iter().count();
if let Some(devtools_root) = self
.core
.tree
.iter()
.find(|node| {
node.key
.as_ref()
.is_some_and(|key| key.as_ref() == crate::devtools::DEVTOOLS_KEY)
})
.map(|node| node.id)
{
let mut stack = vec![devtools_root];
let mut devtools_nodes = 0usize;
while let Some(id) = stack.pop() {
if !self.core.tree.is_valid(id) {
continue;
}
devtools_nodes = devtools_nodes.saturating_add(1);
for &child in &self.core.tree.node(id).children {
stack.push(child);
}
}
node_count = node_count.saturating_sub(devtools_nodes);
}
self.devtools_state
.borrow_mut()
.push_frame_metrics(crate::devtools::FrameMetrics {
timestamp: Instant::now(),
dirty_level: dirty_level_label(draw_mode).to_string(),
total_duration,
reconcile_duration,
draw_duration,
node_count,
overlay_count: self.core.tree.overlay_roots().len(),
memo_hits: u64::from(memo_hits),
memo_misses: u64::from(memo_misses),
});
self.devtools_refresh_pending = true;
}
#[cfg(feature = "devtools")]
pub(super) fn install_devtools_overlay(&mut self) {
if self.devtools_state.borrow().visible {
self.core
.set_extra_root_element(Some(crate::devtools::panel_element(Rc::clone(
&self.devtools_state,
))));
return;
}
self.core.set_extra_root_element(None);
}
}