Skip to content

Commit

Permalink
Add profiling feature with code to ease the ability for developers … (#…
Browse files Browse the repository at this point in the history
…189)

* Add `profiling` feature with code to ease the ability for developers to profile `plotinator3000`

* remove missing_debug_implementations lint. it's just annoying

* refactor to remove the missing_debug_implementations allow lints, and to reduce the number of lines in App:update
  • Loading branch information
CramBL authored Feb 9, 2025
1 parent e214e9a commit c8662a2
Show file tree
Hide file tree
Showing 13 changed files with 254 additions and 81 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [unreleased]

### Added

- Add `profiling` feature with code to ease the ability for developers to profile `plotinator3000`.

### Changed

- Organize test data files etc. in the new `test_util` crate with utilities for generating basic test boiler plate
Expand Down
83 changes: 83 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 12 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ thiserror = "2.0"
semver = "1.0.24"
elevated-command = "1.1"
paste = "1.0.15"
profiling = { version = "1.0.16", default-features = false, features = ["profile-with-puffin"] }
puffin = "0.19"
puffin_http = "0.16"

# Dev dependencies
testresult = "0.4.1"
Expand Down Expand Up @@ -80,16 +83,14 @@ testresult.workspace = true
tempfile.workspace = true
reqwest.workspace = true

[features]
default = ["selfupdater"]
hdf = []
selfupdater = []

# native:
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
env_logger = "0.11"
zip = "2.2.2"
axoupdater = { version = "0.9.0", features = ["blocking"] }
profiling = { workspace = true, optional = true}
puffin = { workspace = true, optional = true}
puffin_http = { workspace = true, optional = true}


# web:
Expand All @@ -101,6 +102,12 @@ web-sys = "0.3.70"
[target.'cfg(target_os = "windows")'.dependencies]
elevated-command.workspace = true

[features]
default = ["selfupdater"]
hdf = []
selfupdater = []
profiling = ["dep:profiling", "dep:puffin", "dep:puffin_http"]

[profile.release]
opt-level = 3
debug = false
Expand All @@ -121,7 +128,6 @@ inherits = "release"
workspace = true

[workspace.lints.rust]
missing_debug_implementations = "warn"
missing_copy_implementations = "warn"
trivial_casts = "warn"
trivial_numeric_casts = "warn"
Expand Down
5 changes: 5 additions & 0 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ update:
audit *ARGS:
cargo audit {{ ARGS }}

[group("Profiling")]
run-profiling *ARGS:
cargo install puffin_viewer --locked
cargo {{run}} --features profiling -- {{ARGS}}

# Trunk is used to serve the app with a webserver, cargo-dist is used to generate and update workflows for distributing installers for various platforms
[doc("Install the required tools for performing all dev tasks for the project")]
install-devtools:
Expand Down
7 changes: 7 additions & 0 deletions crates/plot_util/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,14 @@ egui.workspace = true
serde.workspace = true
chrono.workspace = true
num-traits.workspace = true
profiling = { workspace = true, optional = true}
puffin = { workspace = true, optional = true}
puffin_http = { workspace = true, optional = true}

[dev-dependencies]
testresult.workspace = true
pretty_assertions.workspace = true

[features]
default = []
profiling = ["dep:profiling", "dep:puffin", "dep:puffin_http"]
12 changes: 12 additions & 0 deletions crates/plot_util/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ pub fn plot_lines<'pv>(
mipmap_cfg: MipMapConfiguration,
plots_width_pixels: usize,
) {
#[cfg(all(feature = "profiling", not(target_arch = "wasm32")))]
puffin::profile_function!();
let (x_lower, x_higher) = extended_x_plot_bound(plot_ui.plot_bounds(), 0.1);
for plot_vals in plots {
match mipmap_cfg {
Expand Down Expand Up @@ -66,6 +68,8 @@ fn plot_with_mipmapping(
// if the range is already known then we can skip filtering
known_idx_range: Option<(usize, usize)>,
) {
#[cfg(all(feature = "profiling", not(target_arch = "wasm32")))]
puffin::profile_function!();
let (x_lower, x_higher) = x_range;
// If the mipmap level is 0 or 1 plotting all data points is just as efficient.
if mipmap_lvl < 2 {
Expand Down Expand Up @@ -93,6 +97,8 @@ fn plot_with_mipmapping(

#[inline(always)]
fn extract_range_points(points: &[[f64; 2]], start: usize, end: usize) -> Vec<[f64; 2]> {
#[cfg(all(feature = "profiling", not(target_arch = "wasm32")))]
puffin::profile_function!();
let element_count = end - start + 2;
let mut final_points = Vec::with_capacity(element_count);
final_points.push(points[0]);
Expand All @@ -109,6 +115,8 @@ fn extract_range_points(points: &[[f64; 2]], start: usize, end: usize) -> Vec<[f
}

pub fn plot_labels(plot_ui: &mut egui_plot::PlotUi, plot_data: &PlotData, id_filter: &[u16]) {
#[cfg(all(feature = "profiling", not(target_arch = "wasm32")))]
puffin::profile_function!();
for plot_labels in plot_data
.plot_labels()
.iter()
Expand All @@ -132,6 +140,8 @@ fn plot_raw(
line_width: f32,
x_min_max_ext: (f64, f64),
) {
#[cfg(all(feature = "profiling", not(target_arch = "wasm32")))]
puffin::profile_function!();
let plot_points = plot_vals.get_raw();
let filtered_points = filter_plot_points(plot_points, x_min_max_ext);
let line = Line::new(filtered_points)
Expand Down Expand Up @@ -166,6 +176,8 @@ pub fn extended_x_plot_bound(bounds: PlotBounds, extension_percentage: f64) -> (
/// Filter plot points based on the x plot bounds. Always includes the first and last plot point
/// such that resetting zooms works well even when the plot bounds are outside the data range.
pub fn filter_plot_points(points: &[[f64; 2]], x_range: (f64, f64)) -> Vec<[f64; 2]> {
#[cfg(all(feature = "profiling", not(target_arch = "wasm32")))]
puffin::profile_function!();
let points_len = points.len();
// Don't bother filtering if there's less than 1024 points
if points_len < 1024 {
Expand Down
Loading

0 comments on commit c8662a2

Please sign in to comment.