diff options
author | 2022-12-20 20:41:09 -0800 | |
---|---|---|
committer | 2023-01-09 18:52:38 +0100 | |
commit | 4b6d3797d43acb1d78a292a7ec712a0be7c8f6a2 (patch) | |
tree | 1208a2c5b16a5e67093677df3a2d6bf159bff0f9 | |
parent | c5cd236b7380c3689792934aeaecd2942713fa67 (diff) | |
download | iced-4b6d3797d43acb1d78a292a7ec712a0be7c8f6a2.tar.gz iced-4b6d3797d43acb1d78a292a7ec712a0be7c8f6a2.tar.bz2 iced-4b6d3797d43acb1d78a292a7ec712a0be7c8f6a2.zip |
Restructured everything to make profiling a feature of iced_winit.
Diffstat (limited to '')
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Cargo.toml | 13 | ||||
-rw-r--r-- | docs/images/perfetto.png | bin | 1534270 -> 0 bytes | |||
-rw-r--r-- | examples/integration_wgpu/Cargo.toml | 1 | ||||
-rw-r--r-- | examples/integration_wgpu/src/main.rs | 7 | ||||
-rw-r--r-- | glow/Cargo.toml | 6 | ||||
-rw-r--r-- | glow/src/image.rs | 6 | ||||
-rw-r--r-- | glow/src/quad.rs | 6 | ||||
-rw-r--r-- | glow/src/triangle.rs | 6 | ||||
-rw-r--r-- | glutin/Cargo.toml | 9 | ||||
-rw-r--r-- | glutin/src/application.rs | 12 | ||||
-rw-r--r-- | profiling/Cargo.toml | 15 | ||||
-rw-r--r-- | profiling/README.md | 61 | ||||
-rw-r--r-- | profiling/src/lib.rs | 100 | ||||
-rw-r--r-- | wgpu/Cargo.toml | 28 | ||||
-rw-r--r-- | wgpu/src/backend.rs | 6 | ||||
-rw-r--r-- | wgpu/src/image.rs | 6 | ||||
-rw-r--r-- | wgpu/src/quad.rs | 8 | ||||
-rw-r--r-- | wgpu/src/triangle.rs | 8 | ||||
-rw-r--r-- | winit/Cargo.toml | 22 | ||||
-rw-r--r-- | winit/src/application.rs | 8 | ||||
-rw-r--r-- | winit/src/application/profiler.rs | 101 | ||||
-rw-r--r-- | winit/src/lib.rs | 2 |
23 files changed, 181 insertions, 251 deletions
@@ -4,3 +4,4 @@ pkg/ Cargo.lock .cargo/ dist/ +traces/
\ No newline at end of file @@ -39,13 +39,12 @@ smol = ["iced_futures/smol"] palette = ["iced_core/palette"] # Enables querying system information system = ["iced_winit/system"] -# Enables tracing with Chrome -trace_chrome = [ - "iced_winit/trace", - "iced_wgpu?/trace", - "iced_glow?/trace", +# Enables chrome traces +chrome-trace = [ + "iced_winit/chrome-trace", "iced_glutin?/trace", - "iced_profiling/tracing-chrome" + "iced_wgpu?/tracing", + "iced_glow?/tracing", ] [badges] @@ -59,7 +58,6 @@ members = [ "glow", "glutin", "lazy", - "profiling", "native", "style", "wgpu", @@ -75,7 +73,6 @@ iced_graphics = { version = "0.5", path = "graphics" } iced_winit = { version = "0.6", path = "winit", features = ["application"] } iced_glutin = { version = "0.5", path = "glutin", optional = true } iced_glow = { version = "0.5", path = "glow", optional = true } -iced_profiling = { version = "0.1.0", path = "profiling", optional = true } thiserror = "1.0" [dependencies.image_rs] diff --git a/docs/images/perfetto.png b/docs/images/perfetto.png Binary files differdeleted file mode 100644 index 93e9df15..00000000 --- a/docs/images/perfetto.png +++ /dev/null diff --git a/examples/integration_wgpu/Cargo.toml b/examples/integration_wgpu/Cargo.toml index 9380f659..eaa1df7e 100644 --- a/examples/integration_wgpu/Cargo.toml +++ b/examples/integration_wgpu/Cargo.toml @@ -8,7 +8,6 @@ publish = false [dependencies] iced_winit = { path = "../../winit" } iced_wgpu = { path = "../../wgpu", features = ["webgl"] } -iced_profiling = { path = "../../profiling", features = ["tracing-chrome"]} env_logger = "0.8" [target.'cfg(target_arch = "wasm32")'.dependencies] diff --git a/examples/integration_wgpu/src/main.rs b/examples/integration_wgpu/src/main.rs index e3dfb6fc..70f9a48b 100644 --- a/examples/integration_wgpu/src/main.rs +++ b/examples/integration_wgpu/src/main.rs @@ -16,8 +16,6 @@ use winit::{ event_loop::{ControlFlow, EventLoop}, }; -use iced_profiling::info_span; - #[cfg(target_arch = "wasm32")] use wasm_bindgen::JsCast; #[cfg(target_arch = "wasm32")] @@ -41,9 +39,6 @@ pub fn main() { #[cfg(not(target_arch = "wasm32"))] env_logger::init(); - // Initialize tracing - let _guard = iced_profiling::init(); - // Initialize winit let event_loop = EventLoop::new(); @@ -203,8 +198,6 @@ pub fn main() { } } Event::RedrawRequested(_) => { - let _ = info_span!("Integration_WGPU", "DRAW").entered(); - if resized { let size = window.inner_size(); diff --git a/glow/Cargo.toml b/glow/Cargo.toml index 6c150a74..c126a511 100644 --- a/glow/Cargo.toml +++ b/glow/Cargo.toml @@ -8,7 +8,6 @@ license = "MIT AND OFL-1.1" repository = "https://github.com/iced-rs/iced" [features] -trace = ["iced_profiling"] svg = ["iced_graphics/svg"] image = ["iced_graphics/image"] png = ["iced_graphics/png"] @@ -43,9 +42,8 @@ version = "0.5" path = "../graphics" features = ["font-fallback", "font-icons", "opengl"] -[dependencies.iced_profiling] -version = "0.1.0" -path = "../profiling" +[dependencies.tracing] +version = "0.1.6" optional = true [package.metadata.docs.rs] diff --git a/glow/src/image.rs b/glow/src/image.rs index 351b98fa..d3a25b5b 100644 --- a/glow/src/image.rs +++ b/glow/src/image.rs @@ -21,8 +21,8 @@ use glow::HasContext; use std::cell::RefCell; -#[cfg(feature = "trace")] -use iced_profiling::info_span; +#[cfg(feature = "tracing")] +use tracing::info_span; #[derive(Debug)] pub(crate) struct Pipeline { @@ -151,7 +151,7 @@ impl Pipeline { images: &[layer::Image], layer_bounds: Rectangle<u32>, ) { - #[cfg(feature = "trace")] + #[cfg(feature = "tracing")] let _ = info_span!("Glow::Image", "DRAW").entered(); unsafe { diff --git a/glow/src/quad.rs b/glow/src/quad.rs index fc918bf2..67d9a098 100644 --- a/glow/src/quad.rs +++ b/glow/src/quad.rs @@ -7,8 +7,8 @@ use glow::HasContext; use iced_graphics::layer; use iced_native::Rectangle; -#[cfg(feature = "trace")] -use iced_profiling::info_span; +#[cfg(feature = "tracing")] +use tracing::info_span; #[derive(Debug)] pub enum Pipeline { @@ -45,7 +45,7 @@ impl Pipeline { scale: f32, bounds: Rectangle<u32>, ) { - #[cfg(feature = "trace")] + #[cfg(feature = "tracing")] let _ = info_span!("Glow::Quad", "DRAW").enter(); match self { diff --git a/glow/src/triangle.rs b/glow/src/triangle.rs index 11d24349..42c88455 100644 --- a/glow/src/triangle.rs +++ b/glow/src/triangle.rs @@ -9,8 +9,8 @@ use iced_graphics::triangle::{ColoredVertex2D, Vertex2D}; use glow::HasContext; use std::marker::PhantomData; -#[cfg(feature = "trace")] -use iced_profiling::info_span; +#[cfg(feature = "tracing")] +use tracing::info_span; const DEFAULT_VERTICES: usize = 1_000; const DEFAULT_INDICES: usize = 1_000; @@ -61,7 +61,7 @@ impl Pipeline { transformation: Transformation, scale_factor: f32, ) { - #[cfg(feature = "trace")] + #[cfg(feature = "tracing")] let _ = info_span!("Glow::Triangle", "DRAW").enter(); unsafe { diff --git a/glutin/Cargo.toml b/glutin/Cargo.toml index 6749cb96..304170cd 100644 --- a/glutin/Cargo.toml +++ b/glutin/Cargo.toml @@ -11,7 +11,7 @@ keywords = ["gui", "ui", "graphics", "interface", "widgets"] categories = ["gui"] [features] -trace = ["iced_profiling/tracing-chrome"] +trace = ["iced_winit/trace"] debug = ["iced_winit/debug"] system = ["iced_winit/system"] @@ -37,7 +37,6 @@ version = "0.5" path = "../graphics" features = ["opengl"] -[dependencies.iced_profiling] -version = "0.1.0" -path = "../profiling" -optional = true +[dependencies.tracing] +version = "0.1.6" +optional = true
\ No newline at end of file diff --git a/glutin/src/application.rs b/glutin/src/application.rs index 21051f16..1464bb2d 100644 --- a/glutin/src/application.rs +++ b/glutin/src/application.rs @@ -17,8 +17,8 @@ use iced_winit::{Clipboard, Command, Debug, Proxy, Settings}; use glutin::window::Window; use std::mem::ManuallyDrop; -#[cfg(feature = "trace")] -use iced_profiling::{info_span, instrument::Instrument}; +#[cfg(feature = "tracing")] +use tracing::{info_span, instrument::Instrument}; /// Runs an [`Application`] with an executor, compositor, and the provided /// settings. @@ -39,12 +39,12 @@ where use glutin::ContextBuilder; #[cfg(feature = "trace")] - let _guard = iced_profiling::init(); + let _guard = iced_winit::Profiler::init(); let mut debug = Debug::new(); debug.startup_started(); - #[cfg(feature = "trace")] + #[cfg(feature = "tracing")] let _ = info_span!("Application::Glutin", "RUN").entered(); let mut event_loop = EventLoopBuilder::with_user_event().build(); @@ -147,7 +147,7 @@ where settings.exit_on_close_request, ); - #[cfg(feature = "trace")] + #[cfg(feature = "tracing")] let run_instance = run_instance.instrument(info_span!("Application", "LOOP")); @@ -350,7 +350,7 @@ async fn run_instance<A, E, C>( messages.push(message); } event::Event::RedrawRequested(_) => { - #[cfg(feature = "trace")] + #[cfg(feature = "tracing")] let _ = info_span!("Application", "FRAME").entered(); debug.render_started(); diff --git a/profiling/Cargo.toml b/profiling/Cargo.toml deleted file mode 100644 index 29ee8c9c..00000000 --- a/profiling/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "iced_profiling" -authors = ["Bingus <shankern@protonmail.com>"] -version = "0.1.0" -edition = "2021" -description = "Profiling backend implementations for Iced" - -[dependencies] -tracing = { version = "0.1.37", default-features = false, features = ["std"] } -tracing-core = "0.1.30" -tracing-subscriber = { version = "0.3.16", features = ["registry", "env-filter"] } - -[dependencies.tracing-chrome] -version = "0.7.0" -optional = true diff --git a/profiling/README.md b/profiling/README.md deleted file mode 100644 index f150bcec..00000000 --- a/profiling/README.md +++ /dev/null @@ -1,61 +0,0 @@ -# `iced_profiling` -[] -[](https://crates.io/crates/iced_profiling) -[](https://github.com/iced-rs/iced/blob/master/LICENSE) -[](https://discord.gg/3xZJ65GAhd) - -`iced_profiling` is a crate which implements various tracing backends for Iced. - -It relies on the [tracing](https://crates.io/crates/tracing) crate to collect diagnostics. We currently only support -tracing with `tracing`'s `info_span!` macro, but will consider different logging levels in the future. PRs welcome! - -## Trace backends - -We currently support only Chrome JSON traces using the [tracing-chrome](https://crates.io/crates/tracing-chrome) crate. - -There are plans to add support for [Tracy](https://github.com/wolfpld/tracy) in the near future! - -## Generating a trace file - -### Using Iced's `Application` - -Simply enable your tracing backend of choice (e.g. `trace_chrome`) feature in Iced & run your project. - -```shell -cargo run --features iced/trace_chrome -``` -### Standalone dependency - -You can enable tracing by enabling your tracing backend of choice as a feature of `iced_profiling`. - -```toml -iced_profiling = { version = "0.1.0", features = ["tracing-chrome"]} -``` - -Doing so will require you to initialize the profiler manually like so: - -```rust -let _guard = iced_profiling::init(); -``` - -This reference must be kept alive for the entire duration of your application that you wish to profile. - -## Chrome - -By default, Chrome trace files will be generated in the current working directory: -```shell -path/to/your/project/project_trace_{timestamp}.json -``` - -You also set a specific path by setting the `CHROME_TRACE_FILE` env variable: -```shell -CHROME_TRACE_FILE = ~/Desktop/trace.json cargo run -``` - -If you cannot find your trace file, there may have been a permission issue when trying to generate your file. Be sure to check your cargo manifest directory! - -Once your file is generated, you can view it in Google Chrome at either [ui.perfetto.dev](ui.perfetto.dev) (new) or [chrome://trace](chrome://trace) (old). - -<p align="center"> - <img alt="The native target" src="../docs/images/perfetto.png" width="80%"> -</p>
\ No newline at end of file diff --git a/profiling/src/lib.rs b/profiling/src/lib.rs deleted file mode 100644 index 8fc58fb8..00000000 --- a/profiling/src/lib.rs +++ /dev/null @@ -1,100 +0,0 @@ -use std::time::Duration; -use tracing_subscriber::prelude::*; -use tracing_subscriber::Registry; - -#[cfg(feature = "tracing-chrome")] -use { - tracing_chrome::FlushGuard, - tracing_subscriber::fmt::{format::DefaultFields, FormattedFields}, -}; - -pub use tracing::{info_span, instrument}; - -/// Profiler state. This will likely need to be updated or reworked when adding new tracing backends. -pub struct Profiler { - #[cfg(feature = "tracing-chrome")] - /// [`FlushGuard`] must not be dropped until the application scope is dropped for accurate tracing. - _guard: FlushGuard, -} - -pub fn init() -> Profiler { - // Registry stores the spans & generates unique span IDs - let subscriber = Registry::default(); - - #[cfg(feature = "tracing-chrome")] - let (chrome_layer, guard) = { - let mut layer = tracing_chrome::ChromeLayerBuilder::new(); - - // Optional configurable env var: CHROME_TRACE_FILE=/path/to/trace_file/file.json, - // for uploading to chrome://tracing (old) or ui.perfetto.dev (new). - if let Ok(path) = std::env::var("CHROME_TRACE_FILE") { - layer = layer.file(path); - } else if let Ok(current_dir) = std::env::current_dir() { - let time = std::time::SystemTime::now() - .duration_since(std::time::UNIX_EPOCH) - .unwrap_or(Duration::from_millis(0)) - .as_millis(); - - let trace_file_name = current_dir - .file_name() - .map(|file_dir| { - format!( - "{}_trace_{}.json", - file_dir.to_str().unwrap_or("trace"), - time - ) - }) - .unwrap_or_else(|| "trace.json".to_string()); - - let path = format!( - "{}/{}", - current_dir.to_str().expect("Invalid path"), - trace_file_name - ); - - layer = layer.file(path); - } else { - layer = layer.file(env!("CARGO_MANIFEST_DIR")) - } - - let (chrome_layer, guard) = layer - .name_fn(Box::new(|event_or_span| match event_or_span { - tracing_chrome::EventOrSpan::Event(event) => { - event.metadata().name().into() - } - tracing_chrome::EventOrSpan::Span(span) => { - if let Some(fields) = span - .extensions() - .get::<FormattedFields<DefaultFields>>() - { - format!( - "{}: {}", - span.metadata().name(), - fields.fields.as_str() - ) - } else { - span.metadata().name().into() - } - } - })) - .build(); - - (chrome_layer, guard) - }; - - let fmt_layer = tracing_subscriber::fmt::Layer::default(); - let subscriber = subscriber.with(fmt_layer); - - #[cfg(feature = "tracing-chrome")] - let subscriber = subscriber.with(chrome_layer); - - // create dispatcher which will forward span events to the subscriber - // this can only be set once or will panic - tracing::subscriber::set_global_default(subscriber) - .expect("Profiler could not set the global default subscriber."); - - Profiler { - #[cfg(feature = "tracing-chrome")] - _guard: guard, - } -} diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml index ca89cc26..8dc4b990 100644 --- a/wgpu/Cargo.toml +++ b/wgpu/Cargo.toml @@ -8,25 +8,24 @@ license = "MIT AND OFL-1.1" repository = "https://github.com/iced-rs/iced" [features] -bmp = ["iced_graphics/bmp"] -canvas = ["iced_graphics/canvas"] -dds = ["iced_graphics/dds"] -default_system_font = ["iced_graphics/font-source"] -farbfeld = ["iced_graphics/farbfeld"] -gif = ["iced_graphics/gif"] -hdr = ["iced_graphics/hdr"] -ico = ["iced_graphics/ico"] +svg = ["iced_graphics/svg"] image = ["iced_graphics/image"] +png = ["iced_graphics/png"] jpeg = ["iced_graphics/jpeg"] jpeg_rayon = ["iced_graphics/jpeg_rayon"] -png = ["iced_graphics/png"] +gif = ["iced_graphics/gif"] +webp = ["iced_graphics/webp"] pnm = ["iced_graphics/pnm"] +ico = ["iced_graphics/ico"] +bmp = ["iced_graphics/bmp"] +hdr = ["iced_graphics/hdr"] +dds = ["iced_graphics/dds"] +farbfeld = ["iced_graphics/farbfeld"] +canvas = ["iced_graphics/canvas"] qr_code = ["iced_graphics/qr_code"] +default_system_font = ["iced_graphics/font-source"] spirv = ["wgpu/spirv"] -svg = ["iced_graphics/svg"] -trace = ["iced_profiling"] webgl = ["wgpu/webgl"] -webp = ["iced_graphics/webp"] [dependencies] wgpu = "0.14" @@ -51,9 +50,8 @@ version = "0.5" path = "../graphics" features = ["font-fallback", "font-icons"] -[dependencies.iced_profiling] -version = "0.1.0" -path = "../profiling" +[dependencies.tracing] +version = "0.1.6" optional = true [dependencies.encase] diff --git a/wgpu/src/backend.rs b/wgpu/src/backend.rs index dda9aee1..9ab12ce0 100644 --- a/wgpu/src/backend.rs +++ b/wgpu/src/backend.rs @@ -10,8 +10,8 @@ use iced_graphics::{Primitive, Viewport}; use iced_native::alignment; use iced_native::{Font, Size}; -#[cfg(feature = "trace")] -use iced_profiling::info_span; +#[cfg(feature = "tracing")] +use tracing::info_span; #[cfg(any(feature = "image", feature = "svg"))] use crate::image; @@ -80,7 +80,7 @@ impl Backend { overlay_text: &[T], ) { log::debug!("Drawing"); - #[cfg(feature = "trace")] + #[cfg(feature = "tracing")] let _ = info_span!("Wgpu::Backend", "PRESENT").entered(); let target_size = viewport.physical_size(); diff --git a/wgpu/src/image.rs b/wgpu/src/image.rs index ed81e0c6..a5e63b17 100644 --- a/wgpu/src/image.rs +++ b/wgpu/src/image.rs @@ -23,8 +23,8 @@ use iced_native::image; #[cfg(feature = "svg")] use iced_native::svg; -#[cfg(feature = "trace")] -use iced_profiling::info_span; +#[cfg(feature = "tracing")] +use tracing::info_span; #[derive(Debug)] pub struct Pipeline { @@ -292,7 +292,7 @@ impl Pipeline { target: &wgpu::TextureView, _scale: f32, ) { - #[cfg(feature = "trace")] + #[cfg(feature = "tracing")] let _ = info_span!("Wgpu::Image", "DRAW").entered(); let instances: &mut Vec<Instance> = &mut Vec::new(); diff --git a/wgpu/src/quad.rs b/wgpu/src/quad.rs index 702122e1..2f5fcc6b 100644 --- a/wgpu/src/quad.rs +++ b/wgpu/src/quad.rs @@ -6,8 +6,8 @@ use bytemuck::{Pod, Zeroable}; use std::mem; use wgpu::util::DeviceExt; -#[cfg(feature = "trace")] -use iced_profiling::info_span; +#[cfg(feature = "tracing")] +use tracing::info_span; #[derive(Debug)] pub struct Pipeline { @@ -176,7 +176,7 @@ impl Pipeline { bounds: Rectangle<u32>, target: &wgpu::TextureView, ) { - #[cfg(feature = "trace")] + #[cfg(feature = "tracing")] let _ = info_span!("Wgpu::Quad", "DRAW").entered(); let uniforms = Uniforms::new(transformation, scale); @@ -213,7 +213,7 @@ impl Pipeline { instance_buffer.copy_from_slice(instance_bytes); - #[cfg(feature = "trace")] + #[cfg(feature = "tracing")] let _ = info_span!("Wgpu::Quad", "BEGIN_RENDER_PASS").enter(); { diff --git a/wgpu/src/triangle.rs b/wgpu/src/triangle.rs index b7c63167..efdd214b 100644 --- a/wgpu/src/triangle.rs +++ b/wgpu/src/triangle.rs @@ -8,8 +8,8 @@ use crate::Transformation; use iced_graphics::layer::mesh::{self, Mesh}; use iced_graphics::triangle::ColoredVertex2D; use iced_graphics::Size; -#[cfg(feature = "trace")] -use iced_profiling::info_span; +#[cfg(feature = "tracing")] +use tracing::info_span; #[derive(Debug)] pub struct Pipeline { @@ -55,7 +55,7 @@ impl Pipeline { scale_factor: f32, meshes: &[Mesh<'_>], ) { - #[cfg(feature = "trace")] + #[cfg(feature = "tracing")] let _ = info_span!("Wgpu::Triangle", "DRAW").entered(); // Count the total amount of vertices & indices we need to handle @@ -252,7 +252,7 @@ impl Pipeline { (target, None, wgpu::LoadOp::Load) }; - #[cfg(feature = "trace")] + #[cfg(feature = "tracing")] let _ = info_span!("Wgpu::Triangle", "BEGIN_RENDER_PASS").enter(); let mut render_pass = diff --git a/winit/Cargo.toml b/winit/Cargo.toml index 22b40f70..94aaa2ca 100644 --- a/winit/Cargo.toml +++ b/winit/Cargo.toml @@ -11,7 +11,8 @@ keywords = ["gui", "ui", "graphics", "interface", "widgets"] categories = ["gui"] [features] -trace = ["iced_profiling"] +trace = ["tracing", "tracing-core", "tracing-subscriber"] +chrome-trace = ["trace", "tracing-chrome"] debug = ["iced_native/debug"] system = ["sysinfo"] application = [] @@ -38,9 +39,22 @@ path = "../graphics" version = "0.5" path = "../futures" -[dependencies.iced_profiling] -version = "0.1.0" -path = "../profiling" +[dependencies.tracing] +version = "0.1.37" +optional = true +features = ["std"] + +[dependencies.tracing-core] +version = "0.1.30" +optional = true + +[dependencies.tracing-subscriber] +version = "0.3.16" +optional = true +features = ["registry"] + +[dependencies.tracing-chrome] +version = "0.7.0" optional = true [target.'cfg(target_os = "windows")'.dependencies.winapi] diff --git a/winit/src/application.rs b/winit/src/application.rs index fc73db89..74c73815 100644 --- a/winit/src/application.rs +++ b/winit/src/application.rs @@ -1,4 +1,6 @@ //! Create interactive, native cross-platform applications. +#[cfg(feature = "trace")] +mod profiler; mod state; pub use state::State; @@ -25,7 +27,9 @@ pub use iced_native::application::{Appearance, StyleSheet}; use std::mem::ManuallyDrop; #[cfg(feature = "trace")] -use iced_profiling::{info_span, instrument::Instrument}; +pub use profiler::Profiler; +#[cfg(feature = "trace")] +use tracing::{info_span, instrument::Instrument}; /// An interactive, native cross-platform application. /// @@ -115,7 +119,7 @@ where use winit::event_loop::EventLoopBuilder; #[cfg(feature = "trace")] - let _guard = iced_profiling::init(); + let _guard = Profiler::init(); let mut debug = Debug::new(); debug.startup_started(); diff --git a/winit/src/application/profiler.rs b/winit/src/application/profiler.rs new file mode 100644 index 00000000..23eaa390 --- /dev/null +++ b/winit/src/application/profiler.rs @@ -0,0 +1,101 @@ +//! A simple profiler for Iced. +use std::ffi::OsStr; +use std::path::Path; +use std::time::Duration; +use tracing_subscriber::prelude::*; +use tracing_subscriber::Registry; +#[cfg(feature = "chrome-trace")] +use { + tracing_chrome::FlushGuard, + tracing_subscriber::fmt::{format::DefaultFields, FormattedFields}, +}; + +/// Profiler state. This will likely need to be updated or reworked when adding new tracing backends. +#[allow(missing_debug_implementations)] +pub struct Profiler { + #[cfg(feature = "chrome-trace")] + /// [`FlushGuard`] must not be dropped until the application scope is dropped for accurate tracing. + _guard: FlushGuard, +} + +impl Profiler { + /// Initializes the [`Profiler`]. + pub fn init() -> Self { + // Registry stores the spans & generates unique span IDs + let subscriber = Registry::default(); + + let default_path = Path::new(env!("CARGO_MANIFEST_DIR")); + let curr_exe = std::env::current_exe() + .unwrap_or_else(|_| default_path.to_path_buf()); + let out_dir = curr_exe.parent().unwrap_or(default_path).join("traces"); + + #[cfg(feature = "chrome-trace")] + let (chrome_layer, guard) = { + let mut layer = tracing_chrome::ChromeLayerBuilder::new(); + + // Optional configurable env var: CHROME_TRACE_FILE=/path/to/trace_file/file.json, + // for uploading to chrome://tracing (old) or ui.perfetto.dev (new). + if let Ok(path) = std::env::var("CHROME_TRACE_FILE") { + layer = layer.file(path); + } else if std::fs::create_dir_all(&out_dir).is_ok() { + let time = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap_or(Duration::from_millis(0)) + .as_millis(); + + let curr_exe_name = curr_exe + .file_name() + .unwrap_or_else(|| OsStr::new("trace")) + .to_str() + .unwrap_or("trace"); + + let path = out_dir + .join(format!("{}_trace_{}.json", curr_exe_name, time)); + + layer = layer.file(path); + } else { + layer = layer.file(env!("CARGO_MANIFEST_DIR")) + } + + let (chrome_layer, guard) = layer + .name_fn(Box::new(|event_or_span| match event_or_span { + tracing_chrome::EventOrSpan::Event(event) => { + event.metadata().name().into() + } + tracing_chrome::EventOrSpan::Span(span) => { + if let Some(fields) = span + .extensions() + .get::<FormattedFields<DefaultFields>>() + { + format!( + "{}: {}", + span.metadata().name(), + fields.fields.as_str() + ) + } else { + span.metadata().name().into() + } + } + })) + .build(); + + (chrome_layer, guard) + }; + + let fmt_layer = tracing_subscriber::fmt::Layer::default(); + let subscriber = subscriber.with(fmt_layer); + + #[cfg(feature = "chrome-trace")] + let subscriber = subscriber.with(chrome_layer); + + // create dispatcher which will forward span events to the subscriber + // this can only be set once or will panic + tracing::subscriber::set_global_default(subscriber) + .expect("Tracer could not set the global default subscriber."); + + Profiler { + #[cfg(feature = "chrome-trace")] + _guard: guard, + } + } +} diff --git a/winit/src/lib.rs b/winit/src/lib.rs index b8ed492d..06674109 100644 --- a/winit/src/lib.rs +++ b/winit/src/lib.rs @@ -51,6 +51,8 @@ mod proxy; #[cfg(feature = "application")] pub use application::Application; +#[cfg(feature = "trace")] +pub use application::Profiler; pub use clipboard::Clipboard; pub use error::Error; pub use position::Position; |