Introduce iced_sentinel and iced_debug crates
This commit is contained in:
parent
58a7007ac1
commit
dd36893f7a
26 changed files with 543 additions and 567 deletions
|
|
@ -1,220 +0,0 @@
|
|||
#![allow(missing_docs)]
|
||||
use crate::core::time;
|
||||
|
||||
use std::collections::VecDeque;
|
||||
|
||||
/// A bunch of time measurements for debugging purposes.
|
||||
#[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 {
|
||||
/// Creates a new [`struct@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
|
||||
}
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
#![allow(missing_docs)]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Debug;
|
||||
|
||||
impl Debug {
|
||||
pub fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
|
||||
pub fn startup_started(&mut self) {}
|
||||
|
||||
pub fn startup_finished(&mut self) {}
|
||||
|
||||
pub fn update_started(&mut self) {}
|
||||
|
||||
pub fn update_finished(&mut self) {}
|
||||
|
||||
pub fn view_started(&mut self) {}
|
||||
|
||||
pub fn view_finished(&mut self) {}
|
||||
|
||||
pub fn layout_started(&mut self) {}
|
||||
|
||||
pub fn layout_finished(&mut self) {}
|
||||
|
||||
pub fn event_processing_started(&mut self) {}
|
||||
|
||||
pub fn event_processing_finished(&mut self) {}
|
||||
|
||||
pub fn draw_started(&mut self) {}
|
||||
|
||||
pub fn draw_finished(&mut self) {}
|
||||
|
||||
pub fn render_started(&mut self) {}
|
||||
|
||||
pub fn render_finished(&mut self) {}
|
||||
|
||||
pub fn log_message<Message: std::fmt::Debug>(
|
||||
&mut self,
|
||||
_message: &Message,
|
||||
) {
|
||||
}
|
||||
|
||||
pub fn overlay(&self) -> Vec<String> {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
|
@ -29,20 +29,11 @@ pub mod window;
|
|||
#[cfg(feature = "multi-window")]
|
||||
pub mod multi_window;
|
||||
|
||||
// We disable debug capabilities on release builds unless the `debug` feature
|
||||
// is explicitly enabled.
|
||||
#[cfg(feature = "debug")]
|
||||
#[path = "debug/basic.rs"]
|
||||
mod debug;
|
||||
#[cfg(not(feature = "debug"))]
|
||||
#[path = "debug/null.rs"]
|
||||
mod debug;
|
||||
|
||||
pub use iced_core as core;
|
||||
pub use iced_debug as debug;
|
||||
pub use iced_futures as futures;
|
||||
|
||||
pub use command::Command;
|
||||
pub use debug::Debug;
|
||||
pub use font::Font;
|
||||
pub use program::Program;
|
||||
pub use user_interface::UserInterface;
|
||||
|
|
|
|||
|
|
@ -4,8 +4,9 @@ use crate::core::mouse;
|
|||
use crate::core::renderer;
|
||||
use crate::core::widget::operation::{self, Operation};
|
||||
use crate::core::{Clipboard, Size};
|
||||
use crate::debug;
|
||||
use crate::user_interface::{self, UserInterface};
|
||||
use crate::{Command, Debug, Program};
|
||||
use crate::{Command, Program};
|
||||
|
||||
/// The execution state of a multi-window [`Program`]. It leverages caching, event
|
||||
/// processing, and rendering primitive storage.
|
||||
|
|
@ -27,18 +28,12 @@ where
|
|||
{
|
||||
/// Creates a new [`State`] with the provided [`Program`], initializing its
|
||||
/// primitive with the given logical bounds and renderer.
|
||||
pub fn new(
|
||||
program: P,
|
||||
bounds: Size,
|
||||
renderer: &mut P::Renderer,
|
||||
debug: &mut Debug,
|
||||
) -> Self {
|
||||
pub fn new(program: P, bounds: Size, renderer: &mut P::Renderer) -> Self {
|
||||
let user_interface = build_user_interface(
|
||||
&program,
|
||||
user_interface::Cache::default(),
|
||||
renderer,
|
||||
bounds,
|
||||
debug,
|
||||
);
|
||||
|
||||
let caches = Some(vec![user_interface.into_cache()]);
|
||||
|
|
@ -95,17 +90,15 @@ where
|
|||
theme: &P::Theme,
|
||||
style: &renderer::Style,
|
||||
clipboard: &mut dyn Clipboard,
|
||||
debug: &mut Debug,
|
||||
) -> (Vec<Event>, Option<Command<P::Message>>) {
|
||||
let mut user_interfaces = build_user_interfaces(
|
||||
&self.program,
|
||||
self.caches.take().unwrap(),
|
||||
renderer,
|
||||
bounds,
|
||||
debug,
|
||||
);
|
||||
|
||||
debug.event_processing_started();
|
||||
let interact_timer = debug::interact_time();
|
||||
let mut messages = Vec::new();
|
||||
|
||||
let uncaptured_events = user_interfaces.iter_mut().fold(
|
||||
|
|
@ -135,17 +128,15 @@ where
|
|||
|
||||
self.queued_events.clear();
|
||||
messages.append(&mut self.queued_messages);
|
||||
debug.event_processing_finished();
|
||||
drop(interact_timer);
|
||||
|
||||
let commands = if messages.is_empty() {
|
||||
debug.draw_started();
|
||||
|
||||
let draw_timer = debug::draw_time();
|
||||
for ui in &mut user_interfaces {
|
||||
self.mouse_interaction =
|
||||
ui.draw(renderer, theme, style, cursor);
|
||||
}
|
||||
|
||||
debug.draw_finished();
|
||||
drop(draw_timer);
|
||||
|
||||
self.caches = Some(
|
||||
user_interfaces
|
||||
|
|
@ -164,11 +155,11 @@ where
|
|||
drop(user_interfaces);
|
||||
|
||||
let commands = Command::batch(messages.into_iter().map(|msg| {
|
||||
debug.log_message(&msg);
|
||||
debug::log_message(&msg);
|
||||
|
||||
debug.update_started();
|
||||
let update_timer = debug::update_time();
|
||||
let command = self.program.update(msg);
|
||||
debug.update_finished();
|
||||
drop(update_timer);
|
||||
|
||||
command
|
||||
}));
|
||||
|
|
@ -178,15 +169,14 @@ where
|
|||
temp_caches,
|
||||
renderer,
|
||||
bounds,
|
||||
debug,
|
||||
);
|
||||
|
||||
debug.draw_started();
|
||||
let draw_timer = debug::draw_time();
|
||||
for ui in &mut user_interfaces {
|
||||
self.mouse_interaction =
|
||||
ui.draw(renderer, theme, style, cursor);
|
||||
}
|
||||
debug.draw_finished();
|
||||
drop(draw_timer);
|
||||
|
||||
self.caches = Some(
|
||||
user_interfaces
|
||||
|
|
@ -207,14 +197,12 @@ where
|
|||
renderer: &mut P::Renderer,
|
||||
operations: impl Iterator<Item = Box<dyn Operation<P::Message>>>,
|
||||
bounds: Size,
|
||||
debug: &mut Debug,
|
||||
) {
|
||||
let mut user_interfaces = build_user_interfaces(
|
||||
&self.program,
|
||||
self.caches.take().unwrap(),
|
||||
renderer,
|
||||
bounds,
|
||||
debug,
|
||||
);
|
||||
|
||||
for operation in operations {
|
||||
|
|
@ -251,13 +239,10 @@ fn build_user_interfaces<'a, P: Program>(
|
|||
mut caches: Vec<user_interface::Cache>,
|
||||
renderer: &mut P::Renderer,
|
||||
size: Size,
|
||||
debug: &mut Debug,
|
||||
) -> Vec<UserInterface<'a, P::Message, P::Theme, P::Renderer>> {
|
||||
caches
|
||||
.drain(..)
|
||||
.map(|cache| {
|
||||
build_user_interface(program, cache, renderer, size, debug)
|
||||
})
|
||||
.map(|cache| build_user_interface(program, cache, renderer, size))
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
|
@ -266,15 +251,14 @@ fn build_user_interface<'a, P: Program>(
|
|||
cache: user_interface::Cache,
|
||||
renderer: &mut P::Renderer,
|
||||
size: Size,
|
||||
debug: &mut Debug,
|
||||
) -> UserInterface<'a, P::Message, P::Theme, P::Renderer> {
|
||||
debug.view_started();
|
||||
let view_timer = debug::view_time();
|
||||
let view = program.view();
|
||||
debug.view_finished();
|
||||
drop(view_timer);
|
||||
|
||||
debug.layout_started();
|
||||
let layout_timer = debug::layout_time();
|
||||
let user_interface = UserInterface::build(view, size, cache, renderer);
|
||||
debug.layout_finished();
|
||||
drop(layout_timer);
|
||||
|
||||
user_interface
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@ use crate::core::mouse;
|
|||
use crate::core::renderer;
|
||||
use crate::core::widget::operation::{self, Operation};
|
||||
use crate::core::{Clipboard, Size};
|
||||
use crate::debug;
|
||||
use crate::user_interface::{self, UserInterface};
|
||||
use crate::{Command, Debug, Program};
|
||||
use crate::{Command, Program};
|
||||
|
||||
/// The execution state of a [`Program`]. It leverages caching, event
|
||||
/// processing, and rendering primitive storage.
|
||||
|
|
@ -30,14 +31,12 @@ where
|
|||
mut program: P,
|
||||
bounds: Size,
|
||||
renderer: &mut P::Renderer,
|
||||
debug: &mut Debug,
|
||||
) -> Self {
|
||||
let user_interface = build_user_interface(
|
||||
&mut program,
|
||||
user_interface::Cache::default(),
|
||||
renderer,
|
||||
bounds,
|
||||
debug,
|
||||
);
|
||||
|
||||
let cache = Some(user_interface.into_cache());
|
||||
|
|
@ -94,17 +93,15 @@ where
|
|||
theme: &P::Theme,
|
||||
style: &renderer::Style,
|
||||
clipboard: &mut dyn Clipboard,
|
||||
debug: &mut Debug,
|
||||
) -> (Vec<Event>, Option<Command<P::Message>>) {
|
||||
let mut user_interface = build_user_interface(
|
||||
&mut self.program,
|
||||
self.cache.take().unwrap(),
|
||||
renderer,
|
||||
bounds,
|
||||
debug,
|
||||
);
|
||||
|
||||
debug.event_processing_started();
|
||||
let interact_timer = debug::interact_time();
|
||||
let mut messages = Vec::new();
|
||||
|
||||
let (_, event_statuses) = user_interface.update(
|
||||
|
|
@ -127,13 +124,13 @@ where
|
|||
|
||||
self.queued_events.clear();
|
||||
messages.append(&mut self.queued_messages);
|
||||
debug.event_processing_finished();
|
||||
drop(interact_timer);
|
||||
|
||||
let command = if messages.is_empty() {
|
||||
debug.draw_started();
|
||||
let draw_timer = debug::draw_time();
|
||||
self.mouse_interaction =
|
||||
user_interface.draw(renderer, theme, style, cursor);
|
||||
debug.draw_finished();
|
||||
drop(draw_timer);
|
||||
|
||||
self.cache = Some(user_interface.into_cache());
|
||||
|
||||
|
|
@ -145,11 +142,11 @@ where
|
|||
|
||||
let commands =
|
||||
Command::batch(messages.into_iter().map(|message| {
|
||||
debug.log_message(&message);
|
||||
debug::log_message(&message);
|
||||
|
||||
debug.update_started();
|
||||
let update_timer = debug::update_time();
|
||||
let command = self.program.update(message);
|
||||
debug.update_finished();
|
||||
drop(update_timer);
|
||||
|
||||
command
|
||||
}));
|
||||
|
|
@ -159,13 +156,12 @@ where
|
|||
temp_cache,
|
||||
renderer,
|
||||
bounds,
|
||||
debug,
|
||||
);
|
||||
|
||||
debug.draw_started();
|
||||
let draw_timer = debug::draw_time();
|
||||
self.mouse_interaction =
|
||||
user_interface.draw(renderer, theme, style, cursor);
|
||||
debug.draw_finished();
|
||||
drop(draw_timer);
|
||||
|
||||
self.cache = Some(user_interface.into_cache());
|
||||
|
||||
|
|
@ -181,14 +177,12 @@ where
|
|||
renderer: &mut P::Renderer,
|
||||
operations: impl Iterator<Item = Box<dyn Operation<P::Message>>>,
|
||||
bounds: Size,
|
||||
debug: &mut Debug,
|
||||
) {
|
||||
let mut user_interface = build_user_interface(
|
||||
&mut self.program,
|
||||
self.cache.take().unwrap(),
|
||||
renderer,
|
||||
bounds,
|
||||
debug,
|
||||
);
|
||||
|
||||
for operation in operations {
|
||||
|
|
@ -218,15 +212,14 @@ fn build_user_interface<'a, P: Program>(
|
|||
cache: user_interface::Cache,
|
||||
renderer: &mut P::Renderer,
|
||||
size: Size,
|
||||
debug: &mut Debug,
|
||||
) -> UserInterface<'a, P::Message, P::Theme, P::Renderer> {
|
||||
debug.view_started();
|
||||
let view_timer = debug::view_time();
|
||||
let view = program.view();
|
||||
debug.view_finished();
|
||||
drop(view_timer);
|
||||
|
||||
debug.layout_started();
|
||||
let layout_timer = debug::layout_time();
|
||||
let user_interface = UserInterface::build(view, size, cache, renderer);
|
||||
debug.layout_finished();
|
||||
drop(layout_timer);
|
||||
|
||||
user_interface
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue