Skip to content

Commit

Permalink
Initial profiling support for Iced.
Browse files Browse the repository at this point in the history
  • Loading branch information
bungoboingo committed Nov 30, 2022
1 parent 23da5a3 commit 7e682e7
Show file tree
Hide file tree
Showing 20 changed files with 357 additions and 35 deletions.
10 changes: 10 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ 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",
"iced_glutin?/trace",
"iced_profiling/tracing-chrome"
]

[badges]
maintenance = { status = "actively-developed" }
Expand All @@ -51,6 +59,7 @@ members = [
"glow",
"glutin",
"lazy",
"profiling",
"native",
"style",
"wgpu",
Expand Down Expand Up @@ -99,6 +108,7 @@ iced_graphics = { version = "0.4", path = "graphics" }
iced_winit = { version = "0.5", path = "winit", features = ["application"] }
iced_glutin = { version = "0.4", path = "glutin", optional = true }
iced_glow = { version = "0.4", path = "glow", optional = true }
iced_profiling = { version = "0.1.0", path = "profiling", optional = true }
thiserror = "1.0"

[dependencies.image_rs]
Expand Down
Binary file added docs/images/perfetto.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions examples/integration_wgpu/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ 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]
Expand Down
7 changes: 7 additions & 0 deletions examples/integration_wgpu/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ use winit::{
event_loop::{ControlFlow, EventLoop},
};

use iced_profiling::info_span;

#[cfg(target_arch = "wasm32")]
use wasm_bindgen::JsCast;
#[cfg(target_arch = "wasm32")]
Expand All @@ -39,6 +41,9 @@ 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();

Expand Down Expand Up @@ -198,6 +203,8 @@ pub fn main() {
}
}
Event::RedrawRequested(_) => {
let _ = info_span!("Integration_WGPU", "DRAW").entered();

if resized {
let size = window.inner_size();

Expand Down
6 changes: 6 additions & 0 deletions glow/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ 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"]
Expand Down Expand Up @@ -42,6 +43,11 @@ version = "0.4"
path = "../graphics"
features = ["font-fallback", "font-icons", "opengl"]

[dependencies.iced_profiling]
version = "0.1.0"
path = "../profiling"
optional = true

[package.metadata.docs.rs]
rustdoc-args = ["--cfg", "docsrs"]
all-features = true
6 changes: 6 additions & 0 deletions glow/src/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ use glow::HasContext;

use std::cell::RefCell;

#[cfg(feature = "trace")]
use iced_profiling::info_span;

#[derive(Debug)]
pub(crate) struct Pipeline {
program: <glow::Context as HasContext>::Program,
Expand Down Expand Up @@ -148,6 +151,9 @@ impl Pipeline {
images: &[layer::Image],
layer_bounds: Rectangle<u32>,
) {
#[cfg(feature = "trace")]
let _ = info_span!("Glow::Image", "DRAW").entered();

unsafe {
gl.use_program(Some(self.program));
gl.bind_vertex_array(Some(self.vertex_array));
Expand Down
6 changes: 6 additions & 0 deletions glow/src/quad.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ use glow::HasContext;
use iced_graphics::layer;
use iced_native::Rectangle;

#[cfg(feature = "trace")]
use iced_profiling::info_span;

#[derive(Debug)]
pub enum Pipeline {
Core(core::Pipeline),
Expand Down Expand Up @@ -42,6 +45,9 @@ impl Pipeline {
scale: f32,
bounds: Rectangle<u32>,
) {
#[cfg(feature = "trace")]
let _ = info_span!("Glow::Quad", "DRAW").enter();

match self {
Pipeline::Core(pipeline) => {
pipeline.draw(
Expand Down
6 changes: 6 additions & 0 deletions glow/src/triangle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ use iced_graphics::triangle::{ColoredVertex2D, Vertex2D};
use glow::HasContext;
use std::marker::PhantomData;

#[cfg(feature = "trace")]
use iced_profiling::info_span;

const DEFAULT_VERTICES: usize = 1_000;
const DEFAULT_INDICES: usize = 1_000;

Expand Down Expand Up @@ -58,6 +61,9 @@ impl Pipeline {
transformation: Transformation,
scale_factor: f32,
) {
#[cfg(feature = "trace")]
let _ = info_span!("Glow::Triangle", "DRAW").enter();

unsafe {
gl.enable(glow::MULTISAMPLE);
gl.enable(glow::SCISSOR_TEST);
Expand Down
6 changes: 6 additions & 0 deletions glutin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ keywords = ["gui", "ui", "graphics", "interface", "widgets"]
categories = ["gui"]

[features]
trace = ["iced_profiling/tracing-chrome"]
debug = ["iced_winit/debug"]
system = ["iced_winit/system"]

Expand All @@ -35,3 +36,8 @@ features = ["application"]
version = "0.4"
path = "../graphics"
features = ["opengl"]

[dependencies.iced_profiling]
version = "0.1.0"
path = "../profiling"
optional = true
44 changes: 32 additions & 12 deletions glutin/src/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ 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};

/// Runs an [`Application`] with an executor, compositor, and the provided
/// settings.
pub fn run<A, E, C>(
Expand All @@ -35,9 +38,15 @@ where
use glutin::platform::run_return::EventLoopExtRunReturn;
use glutin::ContextBuilder;

#[cfg(feature = "trace")]
let _guard = iced_profiling::init();

let mut debug = Debug::new();
debug.startup_started();

#[cfg(feature = "trace")]
let _ = info_span!("Application::Glutin", "RUN").entered();

let mut event_loop = EventLoopBuilder::with_user_event().build();
let proxy = event_loop.create_proxy();

Expand Down Expand Up @@ -124,18 +133,26 @@ where

let (mut sender, receiver) = mpsc::unbounded();

let mut instance = Box::pin(run_instance::<A, E, C>(
application,
compositor,
renderer,
runtime,
proxy,
debug,
receiver,
context,
init_command,
settings.exit_on_close_request,
));
let mut instance = Box::pin({
let run_instance = run_instance::<A, E, C>(
application,
compositor,
renderer,
runtime,
proxy,
debug,
receiver,
context,
init_command,
settings.exit_on_close_request,
);

#[cfg(feature = "trace")]
let run_instance =
run_instance.instrument(info_span!("Application", "LOOP"));

run_instance
});

let mut context = task::Context::from_waker(task::noop_waker_ref());

Expand Down Expand Up @@ -332,6 +349,9 @@ async fn run_instance<A, E, C>(
messages.push(message);
}
event::Event::RedrawRequested(_) => {
#[cfg(feature = "trace")]
let _ = info_span!("Application", "FRAME").entered();

debug.render_started();

#[allow(unsafe_code)]
Expand Down
15 changes: 15 additions & 0 deletions profiling/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[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
61 changes: 61 additions & 0 deletions profiling/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# `iced_profiling`
[![Documentation](https://docs.rs/iced_profiling/badge.svg)]
[![Crates.io](https://img.shields.io/crates/v/iced_profiling.svg)](https://crates.io/crates/iced_profiling)
[![License](https://img.shields.io/crates/l/iced_profiling.svg)](https://github.com/iced-rs/iced/blob/master/LICENSE)
[![Discord Server](https://img.shields.io/discord/628993209984614400?label=&labelColor=6A7EC2&logo=discord&logoColor=ffffff&color=7389D8)](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>
Loading

0 comments on commit 7e682e7

Please sign in to comment.