iced_runtime/debug/
basic.rs#![allow(missing_docs)]
use crate::core::time;
use std::collections::VecDeque;
#[derive(Debug)]
pub struct Debug {
is_enabled: bool,
startup_start: time::Instant,
startup_duration: time::Duration,
update_start: time::Instant,
update_durations: TimeBuffer,
view_start: time::Instant,
view_durations: TimeBuffer,
layout_start: time::Instant,
layout_durations: TimeBuffer,
event_start: time::Instant,
event_durations: TimeBuffer,
draw_start: time::Instant,
draw_durations: TimeBuffer,
render_start: time::Instant,
render_durations: TimeBuffer,
message_count: usize,
last_messages: VecDeque<String>,
}
impl Debug {
pub fn new() -> Self {
let now = time::Instant::now();
Self {
is_enabled: false,
startup_start: now,
startup_duration: time::Duration::from_secs(0),
update_start: now,
update_durations: TimeBuffer::new(200),
view_start: now,
view_durations: TimeBuffer::new(200),
layout_start: now,
layout_durations: TimeBuffer::new(200),
event_start: now,
event_durations: TimeBuffer::new(200),
draw_start: now,
draw_durations: TimeBuffer::new(200),
render_start: now,
render_durations: TimeBuffer::new(50),
message_count: 0,
last_messages: VecDeque::new(),
}
}
pub fn toggle(&mut self) {
self.is_enabled = !self.is_enabled;
}
pub fn startup_started(&mut self) {
self.startup_start = time::Instant::now();
}
pub fn startup_finished(&mut self) {
self.startup_duration = self.startup_start.elapsed();
}
pub fn update_started(&mut self) {
self.update_start = time::Instant::now();
}
pub fn update_finished(&mut self) {
self.update_durations.push(self.update_start.elapsed());
}
pub fn view_started(&mut self) {
self.view_start = time::Instant::now();
}
pub fn view_finished(&mut self) {
self.view_durations.push(self.view_start.elapsed());
}
pub fn layout_started(&mut self) {
self.layout_start = time::Instant::now();
}
pub fn layout_finished(&mut self) {
self.layout_durations.push(self.layout_start.elapsed());
}
pub fn event_processing_started(&mut self) {
self.event_start = time::Instant::now();
}
pub fn event_processing_finished(&mut self) {
self.event_durations.push(self.event_start.elapsed());
}
pub fn draw_started(&mut self) {
self.draw_start = time::Instant::now();
}
pub fn draw_finished(&mut self) {
self.draw_durations.push(self.draw_start.elapsed());
}
pub fn render_started(&mut self) {
self.render_start = time::Instant::now();
}
pub fn render_finished(&mut self) {
self.render_durations.push(self.render_start.elapsed());
}
pub fn log_message<Message: std::fmt::Debug>(&mut self, message: &Message) {
self.last_messages.push_back(format!("{message:?}"));
if self.last_messages.len() > 10 {
let _ = self.last_messages.pop_front();
}
self.message_count += 1;
}
pub fn overlay(&self) -> Vec<String> {
if !self.is_enabled {
return Vec::new();
}
let mut lines = Vec::new();
fn key_value<T: std::fmt::Debug>(key: &str, value: T) -> String {
format!("{key} {value:?}")
}
lines.push(format!(
"{} {} - {}",
env!("CARGO_PKG_NAME"),
env!("CARGO_PKG_VERSION"),
env!("CARGO_PKG_REPOSITORY"),
));
lines.push(key_value("Startup:", self.startup_duration));
lines.push(key_value("Update:", self.update_durations.average()));
lines.push(key_value("View:", self.view_durations.average()));
lines.push(key_value("Layout:", self.layout_durations.average()));
lines.push(key_value(
"Event processing:",
self.event_durations.average(),
));
lines.push(key_value(
"Primitive generation:",
self.draw_durations.average(),
));
lines.push(key_value("Render:", self.render_durations.average()));
lines.push(key_value("Message count:", self.message_count));
lines.push(String::from("Last messages:"));
lines.extend(self.last_messages.iter().map(|msg| {
if msg.len() <= 100 {
format!(" {msg}")
} else {
format!(" {msg:.100}...")
}
}));
lines
}
}
impl Default for Debug {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug)]
struct TimeBuffer {
head: usize,
size: usize,
contents: Vec<time::Duration>,
}
impl TimeBuffer {
fn new(capacity: usize) -> TimeBuffer {
TimeBuffer {
head: 0,
size: 0,
contents: vec![time::Duration::from_secs(0); capacity],
}
}
fn push(&mut self, duration: time::Duration) {
self.head = (self.head + 1) % self.contents.len();
self.contents[self.head] = duration;
self.size = (self.size + 1).min(self.contents.len());
}
fn average(&self) -> time::Duration {
let sum: time::Duration = if self.size == self.contents.len() {
self.contents[..].iter().sum()
} else {
self.contents[..self.size].iter().sum()
};
sum / self.size.max(1) as u32
}
}