From 54deb2dd88d55fc877b13833fd0c5542f922c97b Mon Sep 17 00:00:00 2001 From: William Casarin Date: Sun, 23 Mar 2025 10:43:49 -0700 Subject: [PATCH] switch to profiling crates This switches to the profiling crate for compatible profiling between rust libraries. To enable: $ cargo build --release --features puffin Feel free to experiment with other profiling backends as well! Would be great to get tracy working. --- .envrc | 6 +++--- .gitignore | 1 + Cargo.lock | 4 ++++ Cargo.toml | 3 +++ TODO | 0 crates/notedeck/Cargo.toml | 3 ++- crates/notedeck/src/app.rs | 14 +++++++------- crates/notedeck/src/unknowns.rs | 4 +--- crates/notedeck_chrome/Cargo.toml | 3 ++- crates/notedeck_columns/Cargo.toml | 3 ++- crates/notedeck_columns/src/app.rs | 8 ++------ crates/notedeck_columns/src/images.rs | 18 +++++------------- crates/notedeck_columns/src/ui/mention.rs | 4 +--- .../notedeck_columns/src/ui/note/contents.rs | 14 ++------------ crates/notedeck_columns/src/ui/note/context.rs | 8 ++------ crates/notedeck_columns/src/ui/note/mod.rs | 15 ++++----------- .../src/ui/note/reply_description.rs | 4 +--- .../notedeck_columns/src/ui/profile/picture.rs | 8 ++------ crates/notedeck_columns/src/unknowns.rs | 4 +--- preview | 2 +- 20 files changed, 46 insertions(+), 80 deletions(-) create mode 100644 TODO diff --git a/.envrc b/.envrc index adc0fb5e..8c4b7db2 100644 --- a/.envrc +++ b/.envrc @@ -13,6 +13,6 @@ source scripts/macos_build_secrets.sh || : export PATH=$PATH:$HOME/.cargo/bin export JB55=32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245 -export JACK=npub1sg6plzptd64u62a878hep2kev88swjh3tw00gjsfl8f237lmu63q0uf63m -export VROD=bd1e19980e2c91e6dc657e92c25762ca882eb9272d2579e221f037f93788de91 -export JEFFG=npub1zuuajd7u3sx8xu92yav9jwxpr839cs0kc3q6t56vd5u9q033xmhsk6c2uc +# simple todo reminders +export TODO_FILE=TODO +2>/dev/null todo.sh ls || : diff --git a/.gitignore b/.gitignore index b2f789cc..60c4b796 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .buildcmd +TODO.bak android-config.json build.log perf.data diff --git a/Cargo.lock b/Cargo.lock index e5ea094a..94db6145 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2740,6 +2740,7 @@ dependencies = [ "nostr", "nostrdb", "poll-promise", + "profiling", "puffin", "puffin_egui", "serde", @@ -2765,6 +2766,7 @@ dependencies = [ "egui_extras", "notedeck", "notedeck_columns", + "profiling", "puffin", "puffin_egui", "serde", @@ -2803,6 +2805,7 @@ dependencies = [ "open", "poll-promise", "pretty_assertions", + "profiling", "puffin", "puffin_egui", "rfd", @@ -3487,6 +3490,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d" dependencies = [ "profiling-procmacros", + "puffin", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 2e9b9f72..132d93da 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,6 +62,7 @@ bincode = "1.3.3" mime_guess = "2.0.5" pretty_assertions = "1.4.1" jni = "0.21.1" +profiling = "1.0" [profile.small] inherits = 'release' @@ -84,6 +85,8 @@ eframe = { git = "https://github.com/damus-io/egui", rev = "93cd1cedc1e8eed2b055 egui-winit = { git = "https://github.com/damus-io/egui", rev = "93cd1cedc1e8eed2b055e317226838e37a845aad" } egui_extras = { git = "https://github.com/damus-io/egui", rev = "93cd1cedc1e8eed2b055e317226838e37a845aad" } epaint = { git = "https://github.com/damus-io/egui", rev = "93cd1cedc1e8eed2b055e317226838e37a845aad" } +puffin = { git = "https://github.com/jb55/puffin", package = "puffin", rev = "c6a6242adaf90b6292c0f462d2acd34d96d224d2" } +puffin_egui = { git = "https://github.com/jb55/puffin", package = "puffin_egui", rev = "c6a6242adaf90b6292c0f462d2acd34d96d224d2" } #winit = { git = "https://github.com/damus-io/winit", rev = "14d61a74bee0c9863abe7ef28efae2c4d8bd3743" } #winit = { path = "/home/jb55/dev/github/rust-windowing/winit" } #android-activity = { git = "https://github.com/damus-io/android-activity", rev = "da17773852312a58c3445422dfe477162f2f1265" } diff --git a/TODO b/TODO new file mode 100644 index 00000000..e69de29b diff --git a/crates/notedeck/Cargo.toml b/crates/notedeck/Cargo.toml index a948b73b..aaa55d83 100644 --- a/crates/notedeck/Cargo.toml +++ b/crates/notedeck/Cargo.toml @@ -32,6 +32,7 @@ ehttp = {workspace = true } mime_guess = { workspace = true } egui-winit = { workspace = true } tokenator = { workspace = true } +profiling = { workspace = true } [dev-dependencies] tempfile = { workspace = true } @@ -40,4 +41,4 @@ tempfile = { workspace = true } jni = { workspace = true } [features] -profiling = ["puffin", "puffin_egui"] +puffin = ["puffin_egui", "dep:puffin"] diff --git a/crates/notedeck/src/app.rs b/crates/notedeck/src/app.rs index b107218f..792bbe24 100644 --- a/crates/notedeck/src/app.rs +++ b/crates/notedeck/src/app.rs @@ -76,8 +76,7 @@ fn render_notedeck(notedeck: &mut Notedeck, ctx: &egui::Context) { impl eframe::App for Notedeck { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { - #[cfg(feature = "profiling")] - puffin::GlobalProfiler::lock().new_frame(); + profiling::finish_frame!(); // handle account updates self.accounts.update(&mut self.ndb, &mut self.pool, ctx); @@ -97,7 +96,7 @@ impl eframe::App for Notedeck { } } - #[cfg(feature = "profiling")] + #[cfg(feature = "puffin")] puffin_egui::profiler_window(ctx); } @@ -107,15 +106,16 @@ impl eframe::App for Notedeck { } } -#[cfg(feature = "profiling")] -fn setup_profiling() { +#[cfg(feature = "puffin")] +fn setup_puffin() { + info!("setting up puffin"); puffin::set_scopes_on(true); // tell puffin to collect data } impl Notedeck { pub fn new>(ctx: &egui::Context, data_path: P, args: &[String]) -> Self { - #[cfg(feature = "profiling")] - setup_profiling(); + #[cfg(feature = "puffin")] + setup_puffin(); // Skip the first argument, which is the program name. let (parsed_args, unrecognized_args) = Args::parse(&args[1..]); diff --git a/crates/notedeck/src/unknowns.rs b/crates/notedeck/src/unknowns.rs index 7587726f..ed708977 100644 --- a/crates/notedeck/src/unknowns.rs +++ b/crates/notedeck/src/unknowns.rs @@ -246,6 +246,7 @@ impl UnknownId { /// We return all of this in a HashSet so that we can fetch these from /// remote relays. /// +#[profiling::function] pub fn get_unknown_note_ids<'a>( ndb: &Ndb, cached_note: &CachedNote, @@ -253,9 +254,6 @@ pub fn get_unknown_note_ids<'a>( note: &Note<'a>, ids: &mut HashMap>, ) -> Result<()> { - #[cfg(feature = "profiling")] - puffin::profile_function!(); - // the author pubkey if ndb.get_profile_by_pubkey(txn, note.pubkey()).is_err() { ids.entry(UnknownId::Pubkey(Pubkey::new(*note.pubkey()))) diff --git a/crates/notedeck_chrome/Cargo.toml b/crates/notedeck_chrome/Cargo.toml index b77b4939..74879f8c 100644 --- a/crates/notedeck_chrome/Cargo.toml +++ b/crates/notedeck_chrome/Cargo.toml @@ -23,6 +23,7 @@ tokio = { workspace = true } tracing-appender = { workspace = true } tracing-subscriber = { workspace = true } tracing = { workspace = true } +profiling = { workspace = true } [dev-dependencies] tempfile = { workspace = true } @@ -40,7 +41,7 @@ path = "src/preview.rs" [features] default = [] -profiling = ["notedeck_columns/puffin", "puffin", "puffin_egui"] +puffin = ["profiling/profile-with-puffin", "dep:puffin"] debug-widget-callstack = ["egui/callstack"] debug-interactive-widgets = [] diff --git a/crates/notedeck_columns/Cargo.toml b/crates/notedeck_columns/Cargo.toml index 9a5b3f32..90440685 100644 --- a/crates/notedeck_columns/Cargo.toml +++ b/crates/notedeck_columns/Cargo.toml @@ -49,6 +49,7 @@ uuid = { workspace = true } sha2 = { workspace = true } base64 = { workspace = true } egui-winit = { workspace = true } +profiling = { workspace = true } [target.'cfg(any(target_os = "windows", target_os = "macos", target_os = "linux"))'.dependencies] rfd = "0.15" @@ -62,5 +63,5 @@ security-framework = "2.11.0" [features] default = [] -profiling = ["puffin", "puffin_egui"] +puffin = ["dep:puffin", "profiling/profile-with-puffin"] diff --git a/crates/notedeck_columns/src/app.rs b/crates/notedeck_columns/src/app.rs index 1ab95602..a6031175 100644 --- a/crates/notedeck_columns/src/app.rs +++ b/crates/notedeck_columns/src/app.rs @@ -507,10 +507,8 @@ fn circle_icon(ui: &mut egui::Ui, openness: f32, response: &egui::Response) { } */ +#[profiling::function] fn render_damus_mobile(app: &mut Damus, app_ctx: &mut AppContext<'_>, ui: &mut egui::Ui) { - #[cfg(feature = "profiling")] - puffin::profile_function!(); - //let routes = app.timelines[0].routes.clone(); if !app.columns(app_ctx.accounts).columns().is_empty() @@ -522,10 +520,8 @@ fn render_damus_mobile(app: &mut Damus, app_ctx: &mut AppContext<'_>, ui: &mut e } } +#[profiling::function] fn render_damus_desktop(app: &mut Damus, app_ctx: &mut AppContext<'_>, ui: &mut egui::Ui) { - #[cfg(feature = "profiling")] - puffin::profile_function!(); - let screen_size = ui.ctx().screen_rect().width(); let calc_panel_width = (screen_size / get_active_columns(app_ctx.accounts, &app.decks_cache).num_columns() as f32) diff --git a/crates/notedeck_columns/src/images.rs b/crates/notedeck_columns/src/images.rs index 499d3af0..24396041 100644 --- a/crates/notedeck_columns/src/images.rs +++ b/crates/notedeck_columns/src/images.rs @@ -67,10 +67,8 @@ pub fn aspect_fill( response } +#[profiling::function] pub fn round_image(image: &mut ColorImage) { - #[cfg(feature = "profiling")] - puffin::profile_function!(); - // The radius to the edge of of the avatar circle let edge_radius = image.size[0] as f32 / 2.0; let edge_radius_squared = edge_radius * edge_radius; @@ -114,10 +112,8 @@ pub fn round_image(image: &mut ColorImage) { } } +#[profiling::function] fn process_pfp_bitmap(imgtyp: ImageType, mut image: image::DynamicImage) -> ColorImage { - #[cfg(feature = "profiling")] - puffin::profile_function!(); - match imgtyp { ImageType::Content => { let image_buffer = image.clone().into_rgba8(); @@ -156,10 +152,8 @@ fn process_pfp_bitmap(imgtyp: ImageType, mut image: image::DynamicImage) -> Colo } } +#[profiling::function] fn parse_img_response(response: ehttp::Response, imgtyp: ImageType) -> Result { - #[cfg(feature = "profiling")] - puffin::profile_function!(); - let content_type = response.content_type().unwrap_or_default(); let size_hint = match imgtyp { ImageType::Profile(size) => SizeHint::Size(size, size), @@ -167,16 +161,14 @@ fn parse_img_response(response: ehttp::Response, imgtyp: ImageType) -> Result { } #[allow(clippy::too_many_arguments)] +#[profiling::function] fn mention_ui( ndb: &Ndb, img_cache: &mut Images, @@ -72,9 +73,6 @@ fn mention_ui( size: f32, selectable: bool, ) -> egui::InnerResponse> { - #[cfg(feature = "profiling")] - puffin::profile_function!(); - let link_color = ui.visuals().hyperlink_color; ui.horizontal(|ui| { diff --git a/crates/notedeck_columns/src/ui/note/contents.rs b/crates/notedeck_columns/src/ui/note/contents.rs index c52de72e..db82f6e7 100644 --- a/crates/notedeck_columns/src/ui/note/contents.rs +++ b/crates/notedeck_columns/src/ui/note/contents.rs @@ -60,6 +60,7 @@ impl egui::Widget for &mut NoteContents<'_, '_> { /// Render an inline note preview with a border. These are used when /// notes are references within a note #[allow(clippy::too_many_arguments)] +#[profiling::function] pub fn render_note_preview( ui: &mut egui::Ui, note_context: &mut NoteContext, @@ -68,9 +69,6 @@ pub fn render_note_preview( parent: NoteKey, note_options: NoteOptions, ) -> NoteResponse { - #[cfg(feature = "profiling")] - puffin::profile_function!(); - let note = if let Ok(note) = note_context.ndb.get_note_by_id(txn, id) { // TODO: support other preview kinds if note.kind() == 1 { @@ -118,6 +116,7 @@ pub fn render_note_preview( } #[allow(clippy::too_many_arguments)] +#[profiling::function] fn render_note_contents( ui: &mut egui::Ui, note_context: &mut NoteContext, @@ -125,9 +124,6 @@ fn render_note_contents( note: &Note, options: NoteOptions, ) -> NoteResponse { - #[cfg(feature = "profiling")] - puffin::profile_function!(); - let note_key = note.key().expect("todo: implement non-db notes"); let selectable = options.has_selectable_text(); let mut images: Vec<(String, MediaCacheType)> = vec![]; @@ -197,8 +193,6 @@ fn render_note_contents( }, BlockType::Hashtag => { - #[cfg(feature = "profiling")] - puffin::profile_scope!("hashtag contents"); let resp = ui.colored_label(link_color, format!("#{}", block.as_str())); if resp.clicked() { @@ -223,8 +217,6 @@ fn render_note_contents( } }; if hide_media || !found_supported() { - #[cfg(feature = "profiling")] - puffin::profile_scope!("url contents"); ui.add(Hyperlink::from_label_and_url( RichText::new(block.as_str()).color(link_color), block.as_str(), @@ -233,8 +225,6 @@ fn render_note_contents( } BlockType::Text => { - #[cfg(feature = "profiling")] - puffin::profile_scope!("text contents"); if options.has_scramble_text() { ui.add(egui::Label::new(rot13(block.as_str())).selectable(selectable)); } else { diff --git a/crates/notedeck_columns/src/ui/note/context.rs b/crates/notedeck_columns/src/ui/note/context.rs index 9d1883c1..3bf2426e 100644 --- a/crates/notedeck_columns/src/ui/note/context.rs +++ b/crates/notedeck_columns/src/ui/note/context.rs @@ -97,10 +97,8 @@ impl NoteContextButton { Self::max_distance_between_circles() / Self::expansion_multiple() } + #[profiling::function] pub fn show(ui: &mut egui::Ui, note_key: NoteKey, put_at: Rect) -> egui::Response { - #[cfg(feature = "profiling")] - puffin::profile_function!(); - let id = ui.id().with(("more_options_anim", note_key)); let min_radius = Self::min_radius(); @@ -138,13 +136,11 @@ impl NoteContextButton { response } + #[profiling::function] pub fn menu( ui: &mut egui::Ui, button_response: egui::Response, ) -> Option { - #[cfg(feature = "profiling")] - puffin::profile_function!(); - let mut context_selection: Option = None; stationary_arbitrary_menu_button(ui, button_response, |ui| { diff --git a/crates/notedeck_columns/src/ui/note/mod.rs b/crates/notedeck_columns/src/ui/note/mod.rs index 5168ab2d..6ae5640b 100644 --- a/crates/notedeck_columns/src/ui/note/mod.rs +++ b/crates/notedeck_columns/src/ui/note/mod.rs @@ -307,15 +307,13 @@ impl<'a, 'd> NoteView<'a, 'd> { } } + #[profiling::function] fn note_header( ui: &mut egui::Ui, note_cache: &mut NoteCache, note: &Note, profile: &Result, nostrdb::Error>, ) { - #[cfg(feature = "profiling")] - puffin::profile_function!(); - let note_key = note.key().unwrap(); ui.horizontal(|ui| { @@ -327,9 +325,8 @@ impl<'a, 'd> NoteView<'a, 'd> { }); } + #[profiling::function] fn show_standard(&mut self, ui: &mut egui::Ui) -> NoteResponse { - #[cfg(feature = "profiling")] - puffin::profile_function!(); let note_key = self.note.key().expect("todo: support non-db notes"); let txn = self.note.txn().expect("todo: support non-db notes"); @@ -563,14 +560,12 @@ fn note_hitbox_clicked( } } +#[profiling::function] fn render_note_actionbar( ui: &mut egui::Ui, note_id: &[u8; 32], note_key: NoteKey, ) -> egui::InnerResponse> { - #[cfg(feature = "profiling")] - puffin::profile_function!(); - ui.horizontal(|ui| { let reply_resp = reply_button(ui, note_key); let quote_resp = quote_repost_button(ui, note_key); @@ -590,14 +585,12 @@ fn secondary_label(ui: &mut egui::Ui, s: impl Into) { ui.add(Label::new(RichText::new(s).size(10.0).color(color))); } +#[profiling::function] fn render_reltime( ui: &mut egui::Ui, note_cache: &mut CachedNote, before: bool, ) -> egui::InnerResponse<()> { - #[cfg(feature = "profiling")] - puffin::profile_function!(); - ui.horizontal(|ui| { if before { secondary_label(ui, "⋅"); diff --git a/crates/notedeck_columns/src/ui/note/reply_description.rs b/crates/notedeck_columns/src/ui/note/reply_description.rs index fdbe2141..000f7d1b 100644 --- a/crates/notedeck_columns/src/ui/note/reply_description.rs +++ b/crates/notedeck_columns/src/ui/note/reply_description.rs @@ -8,6 +8,7 @@ use nostrdb::{Note, NoteReply, Transaction}; use super::{contents::NoteContext, NoteOptions}; #[must_use = "Please handle the resulting note action"] +#[profiling::function] pub fn reply_desc( ui: &mut egui::Ui, txn: &Transaction, @@ -15,9 +16,6 @@ pub fn reply_desc( note_context: &mut NoteContext, note_options: NoteOptions, ) -> Option { - #[cfg(feature = "profiling")] - puffin::profile_function!(); - let mut note_action: Option = None; let size = 10.0; let selectable = false; diff --git a/crates/notedeck_columns/src/ui/profile/picture.rs b/crates/notedeck_columns/src/ui/profile/picture.rs index bd0bed43..b09e24c0 100644 --- a/crates/notedeck_columns/src/ui/profile/picture.rs +++ b/crates/notedeck_columns/src/ui/profile/picture.rs @@ -80,6 +80,7 @@ impl<'cache, 'url> ProfilePic<'cache, 'url> { } } +#[profiling::function] fn render_pfp( ui: &mut egui::Ui, img_cache: &mut Images, @@ -87,9 +88,6 @@ fn render_pfp( ui_size: f32, border: Option, ) -> egui::Response { - #[cfg(feature = "profiling")] - puffin::profile_function!(); - // We will want to downsample these so it's not blurry on hi res displays let img_size = 128u32; @@ -116,15 +114,13 @@ fn render_pfp( ) } +#[profiling::function] fn pfp_image( ui: &mut egui::Ui, img: &TextureHandle, size: f32, border: Option, ) -> egui::Response { - #[cfg(feature = "profiling")] - puffin::profile_function!(); - let (rect, response) = ui.allocate_at_least(vec2(size, size), Sense::hover()); if let Some(stroke) = border { draw_bg_border(ui, rect.center(), size, stroke); diff --git a/crates/notedeck_columns/src/unknowns.rs b/crates/notedeck_columns/src/unknowns.rs index 4f0f9b99..adb83583 100644 --- a/crates/notedeck_columns/src/unknowns.rs +++ b/crates/notedeck_columns/src/unknowns.rs @@ -25,6 +25,7 @@ pub fn update_from_columns( } } +#[profiling::function] pub fn get_unknown_ids( txn: &Transaction, unknown_ids: &mut UnknownIds, @@ -32,9 +33,6 @@ pub fn get_unknown_ids( ndb: &Ndb, note_cache: &mut NoteCache, ) -> Result<()> { - #[cfg(feature = "profiling")] - puffin::profile_function!(); - let mut new_cached_notes: Vec<(NoteKey, CachedNote)> = vec![]; for (_kind, timeline) in timeline_cache.timelines.iter() { diff --git a/preview b/preview index 0bbedf34..f644927e 100755 --- a/preview +++ b/preview @@ -1,5 +1,5 @@ #!/usr/bin/env bash # pass --mobile for mobile previews -#RUST_LOG=info cargo run --bin ui_preview --features profiling --release -- "$@" +#RUST_LOG=info cargo run --bin ui_preview --features puffin --release -- "$@" cargo run --bin ui_preview --release -- "$@"