1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
//! # 🚄 Profiler API
//!
//! This provides bindings between the Puffin Profiler library and Ark.
//!
//! ## Usage
//!
//! In `Cargo.toml`:
//! * Add `"profiler"` to the `ark` `features` list.
//!
//! In your `lib.rs` you need a call `require_profiler_api();`.
//! To enable profiling you need to call `ark::setup_profiler!();` from your
//! module entry point.
//!
//! Now you can add profile scopes with `ark::profiler::function!();`
//! in functions you want to profile.
//!
//! You should now be able to see your profile scopes in the ark-client profiler window.
//!
//! It is also recommended that you call `ark::profiler::set_scopes_on(ark::profiler::is_active());`
//! on each frame update, to allow `ark-client` to switch the module profiler on/off.
use crate::ffi::profiler_v0 as ffi;
#[doc(hidden)]
pub use ffi::API as FFI_API;
/// This can be used as the optional argument to the profile macros to mark them
/// as something to show when doing simple profile measurements from ark-client.
pub const INCLUDE_SIMPLE: &str = "_simple";
/// Current time in nanoseconds, from some unspecified event.
///
/// Used for high precision profiling and is only supported for profiling. May return 0 if profiling is not enabled.
/// Can't be used for absolute time determination, only relative difference between calls.
#[inline]
pub fn now_ns() -> i64 {
ffi::now_ns()
}
/// Report Puffin profiler event stream
///
/// Used by the puffin profiler running in user space to report
/// profiler events to the host profiler instance.
#[inline]
pub fn report_thread_stream_info(stream_info: &puffin::StreamInfoRef<'_>) {
let puffin::StreamInfoRef {
stream,
num_scopes,
depth,
range_ns: (range_ns_min, range_ns_max),
} = stream_info;
let stream_meta = ffi::StreamMeta {
num_scopes: *num_scopes as _,
depth: *depth as _,
range_ns_min: *range_ns_min,
range_ns_max: *range_ns_max,
};
ffi::report_thread_stream_info(&stream_meta, stream);
}
/// Is the module-side profiler on?
///
/// Call `puffin::set_scopes_on(ark::profiler::is_active());`
/// at the top of each frame to heed this.
#[inline]
pub fn is_active() -> bool {
ffi::is_active()
}
// re-export key profiling macros from puffin
//
// this makes it easier for the user as they do not have to depend on the
// puffin crate themselves and match the right version.
pub use puffin::profile_function as function;
pub use puffin::profile_scope as scope;
pub use puffin::set_scopes_on;
// The following two macros are used to be able to have some basic scopes that are always enabled,
// even if all scopes are not enabled with `set_scopes_on()`.
// TODO: We should probably move this feature into puffin, and possibly include several levels
// to set granularity for the scopes you want enabled.
/// Like [`function!`] macro, but will always do the scope even if module profiling is disabled.
#[macro_export]
macro_rules! __function_always {
() => {
$crate::__function_always!("");
};
($data:expr) => {
let _profiler_scope = $crate::__puffin::ProfilerScope::new(
$crate::__puffin::current_function_name!(),
$crate::__puffin::current_file_name!(),
$data,
);
};
}
pub use __function_always as function_always;
/// Like [`scope!`] macro, but will always do the scope even if module profiling is disabled.
#[macro_export]
macro_rules! __scope_always {
($id:expr) => {
$crate::__scope_always!($id, "");
};
($id:expr, $data:expr) => {
let _profiler_scope = $crate::__puffin::ProfilerScope::new(
$id,
$crate::__puffin::current_file_name!(),
$data,
);
};
}
pub use __scope_always as scope_always;
/// Call at least once from your Module setup code to enable profiling
/// using the `puffin` profiler.
#[macro_export]
macro_rules! setup_profiler {
() => {
$crate::__puffin::ThreadProfiler::initialize(
$crate::profiler::now_ns,
|_thread_info, stream_info| $crate::profiler::report_thread_stream_info(stream_info),
);
$crate::__puffin::set_scopes_on($crate::profiler::is_active());
};
}