diff --git a/Cargo.lock b/Cargo.lock index 009fe975e62c507d245c19e2259686325eb784cf..3e2ead84baeaede34f2bd1217a5cdb3f8972e867 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1357,6 +1357,19 @@ dependencies = [ "slab", ] +[[package]] +name = "generator" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6bd114ceda131d3b1d665eba35788690ad37f5916457286b32ab6fd3c438dd" +dependencies = [ + "cfg-if", + "libc", + "log", + "rustversion", + "windows", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -1932,6 +1945,19 @@ version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" +[[package]] +name = "loom" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + [[package]] name = "mach2" version = "0.4.2" @@ -2625,6 +2651,20 @@ name = "profiling" version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d" +dependencies = [ + "profiling-procmacros", + "tracy-client", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30" +dependencies = [ + "quote", + "syn 2.0.98", +] [[package]] name = "quick-xml" @@ -2877,6 +2917,7 @@ dependencies = [ "egui_tiles", "enum_dispatch", "mavlink-bindgen", + "profiling", "ring-channel", "serde", "serde_json", @@ -2888,6 +2929,7 @@ dependencies = [ "tokio", "tracing", "tracing-subscriber", + "tracing-tracy", "uuid", ] @@ -3448,6 +3490,38 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "tracing-tracy" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eaa1852afa96e0fe9e44caa53dc0bd2d9d05e0f2611ce09f97f8677af56e4ba" +dependencies = [ + "tracing-core", + "tracing-subscriber", + "tracy-client", +] + +[[package]] +name = "tracy-client" +version = "0.17.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73202d787346a5418f8222eddb5a00f29ea47caf3c7d38a8f2f69f8455fa7c7e" +dependencies = [ + "loom", + "once_cell", + "tracy-client-sys", +] + +[[package]] +name = "tracy-client-sys" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69fff37da548239c3bf9e64a12193d261e8b22b660991c6fd2df057c168f435f" +dependencies = [ + "cc", + "windows-targets 0.52.6", +] + [[package]] name = "ttf-parser" version = "0.25.1" diff --git a/Cargo.toml b/Cargo.toml index 6f2eb0e70259937a5950d6d00427a24b2dce545c..60bd536c6dfdb8946bbcaa6a6e28bed38e6b10b7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,11 +16,7 @@ egui_extras = "0.31" egui_plot = "0.31" egui_file = "0.22" # =========== Asynchronous =========== -tokio = { version = "1.41", features = [ - "rt-multi-thread", - "net", - "sync", -] } +tokio = { version = "1.41", features = ["rt-multi-thread", "net", "sync"] } # =========== Mavlink =========== skyward_mavlink = { git = "https://git.skywarder.eu/avn/swd/mavlink/mavlink-skyward-lib.git", branch = "rust-strum", features = [ "reflection", @@ -44,3 +40,5 @@ anyhow = "1.0" ring-channel = "0.12.0" thiserror = "2.0.7" uuid = { version = "1.12.1", features = ["serde", "v7"] } +profiling = { version = "1.0", features = ["profile-with-tracy"] } +tracing-tracy = "0.11.4" diff --git a/src/main.rs b/src/main.rs index e0c0555099548c1e08966bc6f91be01500c94071..1182687e23093ae4bd215fb9353d26ac008094ee 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,15 +4,15 @@ mod error; mod mavlink; -mod serial; mod message_broker; +mod serial; mod ui; mod utils; use std::sync::LazyLock; use tokio::runtime::Runtime; -use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Layer}; +use tracing_subscriber::{EnvFilter, Layer, layer::SubscriberExt, util::SubscriberInitExt}; use error::ErrInstrument; use mavlink::ReflectionContext; @@ -28,6 +28,7 @@ fn main() -> Result<(), eframe::Error> { let env_filter = EnvFilter::builder().from_env_lossy(); tracing_subscriber::registry() .with(tracing_subscriber::fmt::layer().with_filter(env_filter)) + .with(tracing_tracy::TracyLayer::default()) .init(); // Start Tokio runtime (TODO: decide whether to use Tokio or a simpler thread-based approach) diff --git a/src/mavlink/base.rs b/src/mavlink/base.rs index 063871967cae1df0f5dc50a98d2366a4878caa95..c10d9febcb6086cd7d2b9a62a7002c83508efe85 100644 --- a/src/mavlink/base.rs +++ b/src/mavlink/base.rs @@ -38,6 +38,7 @@ impl TimedMessage { } /// Extract fields from a MavLink message using string keys +#[profiling::function] pub fn extract_from_message<K, T>( message: &MavMessage, fields: impl IntoIterator<Item = K>, diff --git a/src/message_broker.rs b/src/message_broker.rs index dd3c7dc854f8f84d71f75a90f0a648afcc92e8d0..77932cf3501e3ffef906788227b951646eb5e8e3 100644 --- a/src/message_broker.rs +++ b/src/message_broker.rs @@ -12,18 +12,18 @@ use reception_queue::ReceptionQueue; use crate::{ error::ErrInstrument, - mavlink::{byte_parser, Message, TimedMessage}, + mavlink::{Message, TimedMessage, byte_parser}, utils::RingBuffer, }; use anyhow::{Context, Result}; -use ring_channel::{ring_channel, RingReceiver, RingSender}; +use ring_channel::{RingReceiver, RingSender, ring_channel}; use std::{ collections::HashMap, io::Write, num::NonZeroUsize, sync::{ - atomic::{AtomicBool, Ordering}, Arc, Mutex, + atomic::{AtomicBool, Ordering}, }, time::{Duration, Instant}, }; diff --git a/src/ui/composable_view.rs b/src/ui/composable_view.rs index 4abda196b3a203a5e37c705f7877e69b245dcd09..a97e1fde431c136ff59503e85261220e206651d2 100644 --- a/src/ui/composable_view.rs +++ b/src/ui/composable_view.rs @@ -82,6 +82,7 @@ impl eframe::App for ComposableView { match action { PaneAction::SplitH => { if let Some(hovered_tile) = hovered_pane { + profiling::scope!("split_h"); if self.maximized_pane.is_none() { debug!("Called SplitH on tile {:?}", hovered_tile); let hovered_tile_pane = panes_tree @@ -102,6 +103,7 @@ impl eframe::App for ComposableView { } } PaneAction::SplitV => { + profiling::scope!("split_v"); if self.maximized_pane.is_none() { if let Some(hovered_tile) = hovered_pane { debug!("Called SplitV on tile {:?}", hovered_tile); @@ -240,6 +242,9 @@ impl eframe::App for ComposableView { self.behavior.action = Some(action); } + // Used for the profiler + profiling::finish_frame!(); + // UNCOMMENT THIS TO ENABLE CONTINOUS MODE // ctx.request_repaint(); } @@ -285,6 +290,7 @@ impl ComposableView { } /// Retrieves new messages from the message broker and dispatches them to the panes. + #[profiling::function] fn process_messages(&mut self) { let start = Instant::now(); @@ -398,6 +404,7 @@ struct SourceWindow { } impl SourceWindow { + #[profiling::function] fn show_window(&mut self, ui: &mut egui::Ui, message_broker: &mut MessageBroker) { let mut window_is_open = self.visible; let mut can_be_closed = false; diff --git a/src/ui/panes/default.rs b/src/ui/panes/default.rs index 7fc0636bb5df66dbacb55b4d30665830be3f5ce5..0507d4d0fe5db6b36d8988ebe0b729fa6591cfe2 100644 --- a/src/ui/panes/default.rs +++ b/src/ui/panes/default.rs @@ -4,7 +4,7 @@ use tracing::debug; use crate::ui::{ composable_view::{PaneAction, PaneResponse}, - utils::{vertically_centered, SizingMemo}, + utils::{SizingMemo, vertically_centered}, }; #[derive(Clone, Debug, Default, Serialize, Deserialize)] @@ -22,6 +22,7 @@ impl PartialEq for DefaultPane { } impl PaneBehavior for DefaultPane { + #[profiling::function] fn ui(&mut self, ui: &mut egui::Ui, tile_id: egui_tiles::TileId) -> PaneResponse { let mut response = PaneResponse::default(); diff --git a/src/ui/panes/messages_viewer.rs b/src/ui/panes/messages_viewer.rs index 0925854ebcaadc455b723af4d1f53fbdec6bd2f1..f1f63a974adcfe047f4834878b55cbebfde1b751 100644 --- a/src/ui/panes/messages_viewer.rs +++ b/src/ui/panes/messages_viewer.rs @@ -18,6 +18,7 @@ impl PartialEq for MessagesViewerPane { } impl PaneBehavior for MessagesViewerPane { + #[profiling::function] fn ui(&mut self, ui: &mut egui::Ui, _tile_id: egui_tiles::TileId) -> PaneResponse { let mut response = PaneResponse::default(); let label = ui.add_sized(ui.available_size(), Label::new("This is a label")); diff --git a/src/ui/panes/plot.rs b/src/ui/panes/plot.rs index a7c4b5a0e3d9917cb2707e76c6bba7fb43f7e352..9433ed57aaf69194b6b05b78afa4138fac3037c1 100644 --- a/src/ui/panes/plot.rs +++ b/src/ui/panes/plot.rs @@ -2,14 +2,14 @@ mod source_window; use super::PaneBehavior; use crate::{ - mavlink::{extract_from_message, MessageData, TimedMessage, ROCKET_FLIGHT_TM_DATA}, + mavlink::{MessageData, ROCKET_FLIGHT_TM_DATA, TimedMessage, extract_from_message}, ui::composable_view::PaneResponse, }; use egui::{Color32, Vec2b}; use egui_plot::{Legend, Line, PlotPoints}; use egui_tiles::TileId; use serde::{Deserialize, Serialize}; -use source_window::{sources_window, SourceSettings}; +use source_window::{SourceSettings, sources_window}; use std::iter::zip; #[derive(Clone, Default, Debug, Serialize, Deserialize)] @@ -37,6 +37,7 @@ impl PartialEq for Plot2DPane { } impl PaneBehavior for Plot2DPane { + #[profiling::function] fn ui(&mut self, ui: &mut egui::Ui, _: TileId) -> PaneResponse { let mut response = PaneResponse::default(); @@ -86,6 +87,7 @@ impl PaneBehavior for Plot2DPane { self.contains_pointer } + #[profiling::function] fn update(&mut self, messages: &[TimedMessage]) { if !self.state_valid { self.line_data.clear(); diff --git a/src/ui/panes/plot/source_window.rs b/src/ui/panes/plot/source_window.rs index d68fa93ff2401c7e5457f2683af341a73f8fe101..f6def542663b70e9620103083c72a0b304d87db8 100644 --- a/src/ui/panes/plot/source_window.rs +++ b/src/ui/panes/plot/source_window.rs @@ -1,12 +1,13 @@ use crate::{ - mavlink::{MavMessage, Message}, MAVLINK_PROFILE, + mavlink::{MavMessage, Message}, }; use crate::error::ErrInstrument; use super::{LineSettings, MsgSources}; +#[profiling::function] pub fn sources_window(ui: &mut egui::Ui, plot_settings: &mut SourceSettings) { // extract the msg name from the id to show it in the combo box let msg_name = MAVLINK_PROFILE diff --git a/src/ui/persistency/layout_manager.rs b/src/ui/persistency/layout_manager.rs index 173fea11360bf4f0049957d210992ec38417c5b2..c1a0eec604b3ec15caf164e7307c1dee50972fcd 100644 --- a/src/ui/persistency/layout_manager.rs +++ b/src/ui/persistency/layout_manager.rs @@ -58,6 +58,7 @@ impl LayoutManager { } /// Scans the layout directory and reloads the layouts + #[profiling::function] pub fn reload_layouts(&mut self) { if let Ok(files) = self.layouts_path.read_dir() { trace!("Reloading layouts from {:?}", self.layouts_path); @@ -85,6 +86,7 @@ impl LayoutManager { self.layouts.get(&name.into()) } + #[profiling::function] pub fn save_layout(&mut self, name: &str, state: &ComposableViewState) -> anyhow::Result<()> { let path = self.layouts_path.join(name).with_extension("json"); state.to_file(&path)?; @@ -92,6 +94,7 @@ impl LayoutManager { Ok(()) } + #[profiling::function] pub fn load_layout( &mut self, path: impl AsRef<Path>, diff --git a/src/ui/persistency/layout_manager_window.rs b/src/ui/persistency/layout_manager_window.rs index b3cdbdc10b4aa14885f3535f07848c600a618c71..0cd38bfa094d34b0757bf942027ae6c7f19afc1e 100644 --- a/src/ui/persistency/layout_manager_window.rs +++ b/src/ui/persistency/layout_manager_window.rs @@ -34,6 +34,7 @@ impl LayoutManagerWindow { } } + #[profiling::function] pub fn show( &mut self, ctx: &Context, diff --git a/src/ui/widgets/reception_led.rs b/src/ui/widgets/reception_led.rs index 5ff9e904d45956144ce3f25ffa3cbecdc5728609..4c064eab79d3dee4bac8e021f0a6c5bc73eca29c 100644 --- a/src/ui/widgets/reception_led.rs +++ b/src/ui/widgets/reception_led.rs @@ -48,6 +48,7 @@ impl ReceptionLed { } impl Widget for ReceptionLed { + #[profiling::function] fn ui(self, ui: &mut Ui) -> Response { ui.horizontal(|ui| { ui.label("Receiving at:");