diff options
Diffstat (limited to 'third_party/rust/profiling/src')
-rw-r--r-- | third_party/rust/profiling/src/empty_impl.rs | 34 | ||||
-rw-r--r-- | third_party/rust/profiling/src/lib.rs | 78 | ||||
-rw-r--r-- | third_party/rust/profiling/src/optick_impl.rs | 35 | ||||
-rw-r--r-- | third_party/rust/profiling/src/puffin_impl.rs | 26 | ||||
-rw-r--r-- | third_party/rust/profiling/src/superluminal_impl.rs | 65 | ||||
-rw-r--r-- | third_party/rust/profiling/src/tracing_impl.rs | 22 | ||||
-rw-r--r-- | third_party/rust/profiling/src/tracy_impl.rs | 68 | ||||
-rw-r--r-- | third_party/rust/profiling/src/type_check_impl.rs | 25 |
8 files changed, 353 insertions, 0 deletions
diff --git a/third_party/rust/profiling/src/empty_impl.rs b/third_party/rust/profiling/src/empty_impl.rs new file mode 100644 index 0000000000..ac106a10bb --- /dev/null +++ b/third_party/rust/profiling/src/empty_impl.rs @@ -0,0 +1,34 @@ +/// Opens a scope. Two variants: +/// - profiling::scope!(name: &str) - Opens a scope with the given name +/// - profiling::scope!(name: &str, data: &str) - Opens a scope with the given name and an extra +/// datafield. Details of this depend on the API, but it should be a &str. If the extra data is +/// named, it will be named "tag". Some APIs support adding more data (for example, `optic::tag!`) +/// +/// ``` +/// profiling::scope!("outer"); +/// for _ in 0..10 { +/// profiling::scope!("inner", format!("iteration {}").as_str()); +/// } +/// ``` +#[macro_export] +macro_rules! scope { + ($name:expr) => {}; + ($name:expr, $data:expr) => {}; +} + +/// Registers a thread with the profiler API(s). This is usually setting a name for the thread. +/// Two variants: +/// - register_thread!() - Tries to get the name of the thread, or an ID if no name is set +/// - register_thread!(name: &str) - Registers the thread using the given name +#[macro_export] +macro_rules! register_thread { + () => {}; + ($name:expr) => {}; +} + +/// Finishes the frame. This isn't strictly necessary for some kinds of applications but a pretty +/// normal thing to track in games. +#[macro_export] +macro_rules! finish_frame { + () => {}; +} diff --git a/third_party/rust/profiling/src/lib.rs b/third_party/rust/profiling/src/lib.rs new file mode 100644 index 0000000000..75703408d8 --- /dev/null +++ b/third_party/rust/profiling/src/lib.rs @@ -0,0 +1,78 @@ +// +// To use this library, enable one of the feature flags. Each backend implementation provides the +// exact same interface. Only one may be active at a time. +// + +/// Proc macro for creating a scope around the function, using the name of the function for the +/// scope's name +/// +/// This must be done as a proc macro because tracing requires a const string +/// +/// ``` +/// #[profiling::function] +/// fn my_function() { +/// +/// } +/// ``` +#[cfg(feature = "procmacros")] +pub use profiling_procmacros::function; + +#[cfg(feature = "profile-with-puffin")] +pub use puffin; +#[cfg(feature = "profile-with-puffin")] +mod puffin_impl; +#[cfg(feature = "profile-with-puffin")] +pub use puffin_impl::*; + +#[cfg(feature = "profile-with-optick")] +pub use optick; +#[cfg(feature = "profile-with-optick")] +mod optick_impl; +#[cfg(feature = "profile-with-optick")] +pub use optick_impl::*; + +#[cfg(feature = "profile-with-superluminal")] +pub use superluminal_perf; +#[cfg(feature = "profile-with-superluminal")] +mod superluminal_impl; +#[cfg(feature = "profile-with-superluminal")] +pub use superluminal_impl::*; + +#[cfg(feature = "profile-with-tracing")] +pub use tracing; +#[cfg(feature = "profile-with-tracing")] +mod tracing_impl; +#[cfg(feature = "profile-with-tracing")] +pub use tracing_impl::*; + +#[cfg(feature = "profile-with-tracy")] +pub use tracy_client; +#[cfg(feature = "profile-with-tracy")] +mod tracy_impl; +#[cfg(feature = "profile-with-tracy")] +pub use tracy_impl::*; + +#[cfg(feature = "type-check")] +mod type_check_impl; +#[cfg(feature = "type-check")] +pub use type_check_impl::*; + +#[cfg(not(any( + feature = "profile-with-puffin", + feature = "profile-with-optick", + feature = "profile-with-superluminal", + feature = "profile-with-tracing", + feature = "profile-with-tracy", + feature = "type-check" +)))] +mod empty_impl; + +#[cfg(not(any( + feature = "profile-with-puffin", + feature = "profile-with-optick", + feature = "profile-with-superluminal", + feature = "profile-with-tracing", + feature = "profile-with-tracy", + feature = "type-check" +)))] +pub use empty_impl::*; diff --git a/third_party/rust/profiling/src/optick_impl.rs b/third_party/rust/profiling/src/optick_impl.rs new file mode 100644 index 0000000000..b49b1ad44b --- /dev/null +++ b/third_party/rust/profiling/src/optick_impl.rs @@ -0,0 +1,35 @@ +#[macro_export] +macro_rules! scope { + ($name:expr) => { + $crate::optick::event!($name); + }; + // NOTE: I've not been able to get attached data to work with optick + ($name:expr, $data:expr) => { + $crate::optick::event!($name); + $crate::optick::tag!("tag", $data); + }; +} + +#[macro_export] +macro_rules! register_thread { + () => { + let thread_name = std::thread::current() + .name() + .map(|x| x.to_string()) + .unwrap_or_else(|| format!("Thread {:?}", std::thread::current().id())); + + $crate::register_thread!(&thread_name); + }; + ($name:expr) => { + $crate::optick::register_thread($name); + }; +} + +/// Finishes the frame. This isn't strictly necessary for some kinds of applications but a pretty +/// normal thing to track in games. +#[macro_export] +macro_rules! finish_frame { + () => { + $crate::optick::next_frame(); + }; +} diff --git a/third_party/rust/profiling/src/puffin_impl.rs b/third_party/rust/profiling/src/puffin_impl.rs new file mode 100644 index 0000000000..5566648a46 --- /dev/null +++ b/third_party/rust/profiling/src/puffin_impl.rs @@ -0,0 +1,26 @@ +#[macro_export] +macro_rules! scope { + ($name:expr) => { + $crate::puffin::profile_scope!($name); + }; + ($name:expr, $data:expr) => { + $crate::puffin::profile_scope!($name, $data); + }; +} + +#[macro_export] +macro_rules! register_thread { + () => {}; + ($name:expr) => { + // puffin uses the thread name + }; +} + +/// Finishes the frame. This isn't strictly necessary for some kinds of applications but a pretty +/// normal thing to track in games. +#[macro_export] +macro_rules! finish_frame { + () => { + $crate::puffin::GlobalProfiler::lock().new_frame(); + }; +} diff --git a/third_party/rust/profiling/src/superluminal_impl.rs b/third_party/rust/profiling/src/superluminal_impl.rs new file mode 100644 index 0000000000..298df5cbf7 --- /dev/null +++ b/third_party/rust/profiling/src/superluminal_impl.rs @@ -0,0 +1,65 @@ +#[macro_export] +macro_rules! scope { + ($name:expr) => { + let _superluminal_guard = $crate::superluminal::SuperluminalGuard::new($name); + }; + ($name:expr, $data:expr) => { + let _superluminal_guard = + $crate::superluminal::SuperluminalGuard::new_with_data($name, $data); + }; +} + +#[macro_export] +macro_rules! register_thread { + () => { + let thread_name = std::thread::current() + .name() + .map(|x| x.to_string()) + .unwrap_or_else(|| format!("Thread {:?}", std::thread::current().id())); + + $crate::register_thread!(&thread_name); + }; + ($name:expr) => { + $crate::superluminal_perf::set_current_thread_name($name); + }; +} + +#[macro_export] +macro_rules! finish_frame { + () => { + // superluminal does not have a frame end function + }; +} + +// +// RAII wrappers to support superluminal. These are public as they need to be callable from macros +// but are not intended for direct use. +// +#[doc(hidden)] +pub mod superluminal { + pub struct SuperluminalGuard; + + // 0xFFFFFFFF means "use default color" + const DEFAULT_SUPERLUMINAL_COLOR: u32 = 0xFFFFFFFF; + + impl SuperluminalGuard { + pub fn new(name: &str) -> Self { + superluminal_perf::begin_event(name); + SuperluminalGuard + } + + pub fn new_with_data( + name: &str, + data: &str, + ) -> Self { + superluminal_perf::begin_event_with_data(name, data, DEFAULT_SUPERLUMINAL_COLOR); + SuperluminalGuard + } + } + + impl Drop for SuperluminalGuard { + fn drop(&mut self) { + superluminal_perf::end_event(); + } + } +} diff --git a/third_party/rust/profiling/src/tracing_impl.rs b/third_party/rust/profiling/src/tracing_impl.rs new file mode 100644 index 0000000000..9328b017d9 --- /dev/null +++ b/third_party/rust/profiling/src/tracing_impl.rs @@ -0,0 +1,22 @@ +#[macro_export] +macro_rules! scope { + ($name:expr) => { + let _span = $crate::tracing::span!($crate::tracing::Level::INFO, $name); + let _span_entered = _span.enter(); + }; + ($name:expr, $data:expr) => { + let _span = $crate::tracing::span!($crate::tracing::Level::INFO, $name, tag = $data); + let _span_entered = _span.enter(); + }; +} + +#[macro_export] +macro_rules! register_thread { + () => {}; + ($name:expr) => {}; +} + +#[macro_export] +macro_rules! finish_frame { + () => {}; +} diff --git a/third_party/rust/profiling/src/tracy_impl.rs b/third_party/rust/profiling/src/tracy_impl.rs new file mode 100644 index 0000000000..94f8eaf3b5 --- /dev/null +++ b/third_party/rust/profiling/src/tracy_impl.rs @@ -0,0 +1,68 @@ +#[macro_export] +macro_rules! scope { + // Note: literal patterns provided as an optimization since they can skip an allocation. + ($name:literal) => { + // Note: callstack_depth is 0 since this has significant overhead + let _tracy_span = $crate::tracy_client::span!($name, 0); + }; + ($name:literal, $data:expr) => { + // Note: callstack_depth is 0 since this has significant overhead + let _tracy_span = $crate::tracy_client::span!($name, 0); + _tracy_span.emit_text($data); + }; + ($name:expr) => { + let function_name = { + struct S; + let type_name = core::any::type_name::<S>(); + &type_name[..type_name.len() - 3] + }; + let _tracy_span = $crate::tracy_client::Client::running() + .expect("scope! without a running tracy_client::Client") + // Note: callstack_depth is 0 since this has significant overhead + .span_alloc($name, function_name, file!(), line!(), 0); + }; + ($name:expr, $data:expr) => { + let function_name = { + struct S; + let type_name = core::any::type_name::<S>(); + &type_name[..type_name.len() - 3] + }; + let _tracy_span = $crate::tracy_client::Client::running() + .expect("scope! without a running tracy_client::Client") + // Note: callstack_depth is 0 since this has significant overhead + .span_alloc($name, function_name, file!(), line!(), 0); + _tracy_span.emit_text($data); + }; +} + +/// Registers a thread with the profiler API(s). This is usually setting a name for the thread. +/// Two variants: +/// - register_thread!() - Tries to get the name of the thread, or an ID if no name is set +/// - register_thread!(name: &str) - Registers the thread using the given name +#[macro_export] +macro_rules! register_thread { + () => { + let thread_name = std::thread::current() + .name() + .map(|x| x.to_string()) + .unwrap_or_else(|| format!("Thread {:?}", std::thread::current().id())); + + $crate::register_thread!(&thread_name); + }; + ($name:expr) => { + $crate::tracy_client::Client::running() + .expect("register_thread! without a running tracy_client::Client") + .set_thread_name($name); + }; +} + +/// Finishes the frame. This isn't strictly necessary for some kinds of applications but a pretty +/// normal thing to track in games. +#[macro_export] +macro_rules! finish_frame { + () => { + $crate::tracy_client::Client::running() + .expect("finish_frame! without a running tracy_client::Client") + .frame_mark(); + }; +} diff --git a/third_party/rust/profiling/src/type_check_impl.rs b/third_party/rust/profiling/src/type_check_impl.rs new file mode 100644 index 0000000000..717fe73a07 --- /dev/null +++ b/third_party/rust/profiling/src/type_check_impl.rs @@ -0,0 +1,25 @@ +// This backend is intended to force type checking + +#[macro_export] +macro_rules! scope { + ($name:expr) => { + let _: &str = $name; + }; + ($name:expr, $data:expr) => { + let _: &str = $name; + let _: &str = $data; + }; +} + +#[macro_export] +macro_rules! register_thread { + () => {}; + ($name:expr) => { + let _: &str = $name; + }; +} + +#[macro_export] +macro_rules! finish_frame { + () => {}; +} |