diff --git a/crates/egui_demo_lib/README.md b/crates/egui_demo_lib/README.md index 43ca0a0f309..58a5d6305fa 100644 --- a/crates/egui_demo_lib/README.md +++ b/crates/egui_demo_lib/README.md @@ -14,3 +14,19 @@ The demo library is a separate crate for three reasons: * To remove the amount of code in `egui` proper. * To make it easy for 3rd party egui integrations to use it for tests. - See for instance https://github.com/not-fl3/egui-miniquad/blob/master/examples/demo.rs + +This crate also contains benchmarks for egui. +Run them with +```bash +# Run all benchmarks +cargo bench -p egui_demo_lib + +# Run a single benchmark +cargo bench -p egui_demo_lib "benchmark name" + +# Profile benchmarks with cargo-flamegraph (--root flag is necessary for MacOS) +CARGO_PROFILE_BENCH_DEBUG=true cargo flamegraph --bench benchmark --root -p egui_demo_lib -- --bench "benchmark name" + +# Profile with cargo-instruments +CARGO_PROFILE_BENCH_DEBUG=true cargo instruments --profile bench --bench benchmark -p egui_demo_lib -t time -- --bench "benchmark name" +``` diff --git a/crates/egui_demo_lib/benches/benchmark.rs b/crates/egui_demo_lib/benches/benchmark.rs index dab6bdd7b12..331788c9b29 100644 --- a/crates/egui_demo_lib/benches/benchmark.rs +++ b/crates/egui_demo_lib/benches/benchmark.rs @@ -1,11 +1,20 @@ use std::fmt::Write as _; -use criterion::{criterion_group, criterion_main, Criterion}; +use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; use egui::epaint::TextShape; +use egui::load::SizedTexture; +use egui::{Button, Id, TextureId, Ui, UiBuilder, Vec2}; use egui_demo_lib::LOREM_IPSUM_LONG; use rand::Rng as _; +/// Each iteration should be called in their own `Ui` with an intentional id clash, +/// to prevent the Context from building a massive map of `WidgetRects` (which would slow the test, +/// causing unreliable results). +fn create_benchmark_ui(ctx: &egui::Context) -> Ui { + Ui::new(ctx.clone(), Id::new("clashing_id"), UiBuilder::new()) +} + pub fn criterion_benchmark(c: &mut Criterion) { use egui::RawInput; @@ -55,17 +64,62 @@ pub fn criterion_benchmark(c: &mut Criterion) { { let ctx = egui::Context::default(); let _ = ctx.run(RawInput::default(), |ctx| { - egui::CentralPanel::default().show(ctx, |ui| { - c.bench_function("label &str", |b| { - b.iter(|| { + c.bench_function("label &str", |b| { + b.iter_batched_ref( + || create_benchmark_ui(ctx), + |ui| { ui.label("the quick brown fox jumps over the lazy dog"); - }); - }); - c.bench_function("label format!", |b| { - b.iter(|| { + }, + BatchSize::LargeInput, + ); + }); + c.bench_function("label format!", |b| { + b.iter_batched_ref( + || create_benchmark_ui(ctx), + |ui| { ui.label("the quick brown fox jumps over the lazy dog".to_owned()); - }); - }); + }, + BatchSize::LargeInput, + ); + }); + }); + } + + { + let ctx = egui::Context::default(); + let _ = ctx.run(RawInput::default(), |ctx| { + let mut group = c.benchmark_group("button"); + + // To ensure we have a valid image, let's use the font texture. The size + // shouldn't be important for this benchmark. + let image = SizedTexture::new(TextureId::default(), Vec2::splat(16.0)); + + group.bench_function("1_button_text", |b| { + b.iter_batched_ref( + || create_benchmark_ui(ctx), + |ui| { + ui.add(Button::new("Hello World")); + }, + BatchSize::LargeInput, + ); + }); + group.bench_function("2_button_text_image", |b| { + b.iter_batched_ref( + || create_benchmark_ui(ctx), + |ui| { + ui.add(Button::image_and_text(image, "Hello World")); + }, + BatchSize::LargeInput, + ); + }); + group.bench_function("3_button_text_image_right_text", |b| { + b.iter_batched_ref( + || create_benchmark_ui(ctx), + |ui| { + ui.add(Button::image_and_text(image, "Hello World").right_text("⏵")); + }, + BatchSize::LargeInput, + ); }); }); }