mirror of
https://github.com/aljazceru/notedeck.git
synced 2025-12-17 00:44:18 +01:00
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.
This commit is contained in:
6
.envrc
6
.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 || :
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,4 +1,5 @@
|
||||
.buildcmd
|
||||
TODO.bak
|
||||
android-config.json
|
||||
build.log
|
||||
perf.data
|
||||
|
||||
4
Cargo.lock
generated
4
Cargo.lock
generated
@@ -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]]
|
||||
|
||||
@@ -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" }
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -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<P: AsRef<Path>>(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..]);
|
||||
|
||||
@@ -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<UnknownId, HashSet<RelayUrl>>,
|
||||
) -> 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())))
|
||||
|
||||
@@ -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 = []
|
||||
|
||||
|
||||
@@ -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"]
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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<ColorImage> {
|
||||
#[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<Co
|
||||
};
|
||||
|
||||
if content_type.starts_with("image/svg") {
|
||||
#[cfg(feature = "profiling")]
|
||||
puffin::profile_scope!("load_svg");
|
||||
profiling::scope!("load_svg");
|
||||
|
||||
let mut color_image =
|
||||
egui_extras::image::load_svg_bytes_with_size(&response.bytes, Some(size_hint))?;
|
||||
round_image(&mut color_image);
|
||||
Ok(color_image)
|
||||
} else if content_type.starts_with("image/") {
|
||||
#[cfg(feature = "profiling")]
|
||||
puffin::profile_scope!("load_from_memory");
|
||||
profiling::scope!("load_from_memory");
|
||||
let dyn_image = image::load_from_memory(&response.bytes)?;
|
||||
Ok(process_pfp_bitmap(imgtyp, dyn_image))
|
||||
} else {
|
||||
|
||||
@@ -63,6 +63,7 @@ impl egui::Widget for Mention<'_> {
|
||||
}
|
||||
|
||||
#[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<Option<NoteAction>> {
|
||||
#[cfg(feature = "profiling")]
|
||||
puffin::profile_function!();
|
||||
|
||||
let link_color = ui.visuals().hyperlink_color;
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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<NoteContextSelection> {
|
||||
#[cfg(feature = "profiling")]
|
||||
puffin::profile_function!();
|
||||
|
||||
let mut context_selection: Option<NoteContextSelection> = None;
|
||||
|
||||
stationary_arbitrary_menu_button(ui, button_response, |ui| {
|
||||
|
||||
@@ -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::ProfileRecord<'_>, 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<Option<NoteAction>> {
|
||||
#[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<String>) {
|
||||
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, "⋅");
|
||||
|
||||
@@ -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<NoteAction> {
|
||||
#[cfg(feature = "profiling")]
|
||||
puffin::profile_function!();
|
||||
|
||||
let mut note_action: Option<NoteAction> = None;
|
||||
let size = 10.0;
|
||||
let selectable = false;
|
||||
|
||||
@@ -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<Stroke>,
|
||||
) -> 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<Stroke>,
|
||||
) -> 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);
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user