Skip to content

Commit eff6117

Browse files
committed
Add opt-in support for the 'puffin' profiler in eframe
1 parent 973c3f2 commit eff6117

File tree

10 files changed

+100
-5
lines changed

10 files changed

+100
-5
lines changed

Cargo.lock

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

eframe/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ persistence = [
3737
"epi/persistence",
3838
]
3939

40+
# Enable profiling with the puffin crate: https://github.com/EmbarkStudios/puffin
41+
# Only enabled on native, because of the low resolution (1ms) of time keeping in browsers.
42+
# eframe will call `puffin::GlobalProfiler::lock().new_frame()` for you
43+
puffin = ["egui_glow/puffin"]
44+
4045
# enable screen reader support (requires `ctx.options().screen_reader = true;`)
4146
screen_reader = [
4247
"egui-winit/screen_reader",

egui-winit/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ epi_backend = ["epi", "glow"]
3636
# enable opening links in a browser when an egui hyperlink is clicked.
3737
links = ["webbrowser"]
3838

39+
# Enable profiling with the puffin crate: https://github.com/EmbarkStudios/puffin
40+
puffin = ["dep:puffin"]
41+
3942
# experimental support for a screen reader
4043
screen_reader = ["tts"]
4144

@@ -57,6 +60,7 @@ epi = { version = "0.17.0", path = "../epi", optional = true }
5760
arboard = { version = "2.1", optional = true, default-features = false }
5861
dark-light = { version = "0.2.1", optional = true }
5962
glow = { version = "0.11", optional = true }
63+
puffin = { version = "0.13", optional = true }
6064
serde = { version = "1.0", optional = true, features = ["derive"] }
6165
webbrowser = { version = "0.6", optional = true }
6266

egui-winit/src/epi.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ impl EpiIntegration {
230230

231231
let raw_input = self.egui_winit.take_egui_input(window);
232232
let full_output = self.egui_ctx.run(raw_input, |egui_ctx| {
233+
crate::profile_scope!("App::update");
233234
app.update(egui_ctx, &mut self.frame);
234235
});
235236
self.pending_full_output.append(full_output);
@@ -274,17 +275,26 @@ impl EpiIntegration {
274275
pub fn save(&mut self, _app: &mut dyn epi::App, _window: &winit::window::Window) {
275276
#[cfg(feature = "persistence")]
276277
if let Some(storage) = self.frame.storage_mut() {
278+
crate::profile_function!();
279+
277280
if _app.persist_native_window() {
281+
crate::profile_scope!("native_window");
278282
epi::set_value(
279283
storage,
280284
STORAGE_WINDOW_KEY,
281285
&crate::WindowSettings::from_display(_window),
282286
);
283287
}
284288
if _app.persist_egui_memory() {
289+
crate::profile_scope!("egui_memory");
285290
epi::set_value(storage, STORAGE_EGUI_MEMORY_KEY, &*self.egui_ctx.memory());
286291
}
287-
_app.save(storage);
292+
{
293+
crate::profile_scope!("App::save");
294+
_app.save(storage);
295+
}
296+
297+
crate::profile_scope!("Storage::flush");
288298
storage.flush();
289299
}
290300
}

egui-winit/src/lib.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,3 +646,25 @@ fn translate_cursor(cursor_icon: egui::CursorIcon) -> Option<winit::window::Curs
646646
egui::CursorIcon::ZoomOut => Some(winit::window::CursorIcon::ZoomOut),
647647
}
648648
}
649+
650+
// ---------------------------------------------------------------------------
651+
652+
/// Profiling macro for feature "puffin"
653+
#[doc(hidden)]
654+
#[macro_export]
655+
macro_rules! profile_function {
656+
($($arg: tt)*) => {
657+
#[cfg(feature = "puffin")]
658+
puffin::profile_function!($($arg)*);
659+
};
660+
}
661+
662+
/// Profiling macro for feature "puffin"
663+
#[doc(hidden)]
664+
#[macro_export]
665+
macro_rules! profile_scope {
666+
($($arg: tt)*) => {
667+
#[cfg(feature = "puffin")]
668+
puffin::profile_scope!($($arg)*);
669+
};
670+
}

egui/src/containers/frame.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ impl Frame {
4444

4545
pub(crate) fn central_panel(style: &Style) -> Self {
4646
Self {
47-
inner_margin: Margin::symmetric(8.0, 8.0),
47+
inner_margin: Margin::same(8.0),
4848
rounding: Rounding::none(),
4949
fill: style.visuals.window_fill(),
5050
stroke: Default::default(),
@@ -91,7 +91,7 @@ impl Frame {
9191
/// and in dark mode this will be very dark.
9292
pub fn canvas(style: &Style) -> Self {
9393
Self {
94-
inner_margin: Margin::symmetric(10.0, 10.0),
94+
inner_margin: Margin::same(2.0),
9595
rounding: style.visuals.widgets.noninteractive.rounding,
9696
fill: style.visuals.extreme_bg_color,
9797
stroke: style.visuals.window_stroke(),

egui_glow/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ persistence = [
4747
"epi?/persistence",
4848
]
4949

50+
# Enable profiling with the puffin crate: https://github.com/EmbarkStudios/puffin
51+
puffin = ["dep:puffin", "egui-winit?/puffin"]
52+
5053
# experimental support for a screen reader
5154
screen_reader = ["egui-winit?/screen_reader"]
5255

@@ -72,6 +75,7 @@ egui-winit = { version = "0.17.0", path = "../egui-winit", optional = true, defa
7275
"epi_backend",
7376
] }
7477
glutin = { version = "0.28.0", optional = true }
78+
puffin = { version = "0.13", optional = true }
7579

7680
# Web:
7781
[target.'cfg(target_arch = "wasm32")'.dependencies]

egui_glow/src/epi_backend.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,15 +77,20 @@ pub fn run(app_name: &str, native_options: &epi::NativeOptions, app_creator: epi
7777

7878
event_loop.run(move |event, _, control_flow| {
7979
let mut redraw = || {
80+
#[cfg(feature = "puffin")]
81+
puffin::GlobalProfiler::lock().new_frame();
82+
8083
if !is_focused {
8184
// On Mac, a minimized Window uses up all CPU: https://github.com/emilk/egui/issues/325
8285
// We can't know if we are minimized: https://github.com/rust-windowing/winit/issues/208
8386
// But we know if we are focused (in foreground). When minimized, we are not focused.
8487
// However, a user may want an egui with an animation in the background,
8588
// so we still need to repaint quite fast.
89+
crate::profile_scope!("bg_sleep");
8690
std::thread::sleep(std::time::Duration::from_millis(10));
8791
}
8892

93+
crate::profile_scope!("frame");
8994
let screen_size_in_pixels: [u32; 2] = gl_window.window().inner_size().into();
9095

9196
crate::painter::clear(&gl, screen_size_in_pixels, app.clear_color());
@@ -99,7 +104,10 @@ pub fn run(app_name: &str, native_options: &epi::NativeOptions, app_creator: epi
99104

100105
integration.handle_platform_output(gl_window.window(), platform_output);
101106

102-
let clipped_primitives = integration.egui_ctx.tessellate(shapes);
107+
let clipped_primitives = {
108+
crate::profile_scope!("tessellate");
109+
integration.egui_ctx.tessellate(shapes)
110+
};
103111

104112
painter.paint_and_update_textures(
105113
screen_size_in_pixels,
@@ -108,7 +116,10 @@ pub fn run(app_name: &str, native_options: &epi::NativeOptions, app_creator: epi
108116
&textures_delta,
109117
);
110118

111-
gl_window.swap_buffers().unwrap();
119+
{
120+
crate::profile_scope!("swap_buffers");
121+
gl_window.swap_buffers().unwrap();
122+
}
112123

113124
{
114125
*control_flow = if integration.should_quit() {

egui_glow/src/lib.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,25 @@ pub fn check_for_gl_error_impl(gl: &glow::Context, file: &str, line: u32, contex
8585
}
8686
}
8787
}
88+
89+
// ---------------------------------------------------------------------------
90+
91+
/// Profiling macro for feature "puffin"
92+
#[doc(hidden)]
93+
#[macro_export]
94+
macro_rules! profile_function {
95+
($($arg: tt)*) => {
96+
#[cfg(feature = "puffin")]
97+
puffin::profile_function!($($arg)*);
98+
};
99+
}
100+
101+
/// Profiling macro for feature "puffin"
102+
#[doc(hidden)]
103+
#[macro_export]
104+
macro_rules! profile_scope {
105+
($($arg: tt)*) => {
106+
#[cfg(feature = "puffin")]
107+
puffin::profile_scope!($($arg)*);
108+
};
109+
}

egui_glow/src/painter.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ impl Painter {
297297
clipped_primitives: &[egui::ClippedPrimitive],
298298
textures_delta: &egui::TexturesDelta,
299299
) {
300+
crate::profile_function!();
300301
for (id, image_delta) in &textures_delta.set {
301302
self.set_texture(*id, image_delta);
302303
}
@@ -333,6 +334,7 @@ impl Painter {
333334
pixels_per_point: f32,
334335
clipped_primitives: &[egui::ClippedPrimitive],
335336
) {
337+
crate::profile_function!();
336338
self.assert_not_destroyed();
337339

338340
if let Some(ref mut post_process) = self.post_process {
@@ -355,6 +357,7 @@ impl Painter {
355357
}
356358
Primitive::Callback(callback) => {
357359
if callback.rect.is_positive() {
360+
crate::profile_scope!("callback");
358361
// Transform callback rect to physical pixels:
359362
let rect_min_x = pixels_per_point * callback.rect.min.x;
360363
let rect_min_y = pixels_per_point * callback.rect.min.y;
@@ -456,6 +459,8 @@ impl Painter {
456459
// ------------------------------------------------------------------------
457460

458461
pub fn set_texture(&mut self, tex_id: egui::TextureId, delta: &egui::epaint::ImageDelta) {
462+
crate::profile_function!();
463+
459464
self.assert_not_destroyed();
460465

461466
let glow_texture = *self

0 commit comments

Comments
 (0)