Skip to content

Commit

Permalink
Add extended version of puffin::profile_scope!() (#213)
Browse files Browse the repository at this point in the history
# Checklist

* [X] I have read the [Contributor Guide](../CONTRIBUTING.md)
* [X] I have read and agree to the [Code of
Conduct](../CODE_OF_CONDUCT.md)
* [X] I have added a description of my changes and why I'd like them
included in the section below

# Description of Changes

Add extended version of `puffin::profile_scope!()` that expands to an
expression instead of variable

- This allows for profiling scopes to persist for custom scopes, instead
of being limited to block scopes
- Includes doctests and real-world example


# Related Issues

As per request from @chrisduerr in #194
  • Loading branch information
v0x0g authored Jun 25, 2024
1 parent 8a1904d commit 232bf81
Showing 1 changed file with 57 additions and 13 deletions.
70 changes: 57 additions & 13 deletions puffin/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,24 +231,47 @@ macro_rules! profile_function {
};
}

#[allow(clippy::doc_markdown)] // clippy wants to put "MacBook" in ticks 🙄

/// Profile the current scope with the given name (unique in the parent scope).
///
/// This macro is identical to [profile_scope], except that it expands to the expression
/// containing the profiling scope, as opposed to [profile_scope] which expands to a
/// variable (which cannot be accessed due to macro hygiene).
///
/// Names should be descriptive, ASCII and without spaces.
///
/// Example: `profile_scope!("load_mesh");`.
/// This allows for profiling scopes to persist for a custom duration.
///
/// # Example
///
/// ```rust
/// # use std::iter::FromIterator as _;
/// #
/// # pub mod rayon { pub mod prelude {
/// # pub fn for_each_init<T, I>(vec: &std::vec::Vec<T>, init: fn() -> I, body: fn ((I, T)) -> ()) {
/// # }
/// # } }
/// #
/// let some_large_vec = Vec::from_iter(0..1000);
///
/// An optional second argument can be a string (e.g. a mesh name) to help diagnose what was slow.
/// Example: `profile_scope!("load_mesh", mesh_name);`
///
/// Overhead: around 54 ns on Macbook Pro with Apple M1 Max.
/// // Use rayon's parallel for loop over our large iterator
/// rayon::prelude::for_each_init(
/// &some_large_vec,
/// // This gets called to init each work segment, and is passed into the calls
/// // Rayon keeps the profiling scope stored for the entire duration of the work segment
/// // So we can track the entire segment as one, instead of each loop iteration
/// || puffin::profile_scope_custom!("rayon_work_segment"),
/// |((_profiler_scope), i)| {
/// // All calls here gets profiled on the same scope
/// println!("{i}")
/// },
/// );
/// ```
#[macro_export]
macro_rules! profile_scope {
macro_rules! profile_scope_custom {
($name:expr) => {
$crate::profile_scope!($name, "");
$crate::profile_scope_custom!($name, "")
};
($name:expr, $data:expr) => {
let _profiler_scope = if $crate::are_scopes_on() {
($name:expr, $data:expr) => {{
if $crate::are_scopes_on() {
static SCOPE_ID: std::sync::OnceLock<$crate::ScopeId> = std::sync::OnceLock::new();
let scope_id = SCOPE_ID.get_or_init(|| {
$crate::ThreadProfiler::call(|tp| {
Expand All @@ -264,7 +287,28 @@ macro_rules! profile_scope {
Some($crate::ProfilerScope::new(*scope_id, $data))
} else {
None
};
}
}};
}

#[allow(clippy::doc_markdown)] // clippy wants to put "MacBook" in ticks 🙄
/// Profile the current scope with the given name (unique in the parent scope).
///
/// Names should be descriptive, ASCII and without spaces.
///
/// Example: `profile_scope!("load_mesh");`.
///
/// An optional second argument can be a string (e.g. a mesh name) to help diagnose what was slow.
/// Example: `profile_scope!("load_mesh", mesh_name);`
///
/// Overhead: around 54 ns on Macbook Pro with Apple M1 Max.
#[macro_export]
macro_rules! profile_scope {
($name:expr) => {
$crate::profile_scope!($name, "");
};
($name:expr, $data:expr) => {
let _profiler_scope = $crate::profile_scope_custom!($name, $data);
};
}

Expand Down

0 comments on commit 232bf81

Please sign in to comment.