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
//! [`time-graph`] provides always-on profiling for your code, allowing to //! record the execution time of functions, spans inside these functions and the //! full call graph of spans and functions at run-time. //! //! # Core concepts //! //! There are two main concepts in this crate: [`CallSite`] identify a single //! call site in the source, usually a full function. One can then create a //! [`Span`] from any callsite, representing a single execution of the code. //! When executed, the [`Span`] will its elapsed time, and store it in the //! global call graph. //! //! # Controlling data collection //! //! By default, no data is collected until you call [`enable_data_collection`] //! to start collecting timing data. Once you are done running your code, you //! can extract collected data with [`get_full_graph`], and possibly clear all //! collected data using [`clear_collected_data`]. //! //! [`time-graph`]: https://crates.io/crates/time-graph //! //! # Overhead and limitations //! //! When data collection is disabled, this crate adds an overheard around 10 ns //! when calling a function or entering a span. With data collection enabled, //! this crate adds an overhead around 100 ns when calling a function or //! entering a span. //! //! This makes this crate only useful for gathering profiling data on //! function/spans taking at least 1 µs to execute. //! //! # Crate features //! //! This crate has two cargo features: //! //! - **json**: enables json output format for the full call graph //! - **table**: enables pretty-printing the full call graph to a table using //! [term-table](https://crates.io/crates/term-table) #![allow(clippy::redundant_field_names, clippy::needless_return)] pub use time_graph_macros::instrument; #[doc(hidden)] pub use once_cell::sync::Lazy; /// Create a new [`CallSite`] with the given name at the current source /// location. /// /// # Examples /// ``` /// use time_graph::{CallSite, callsite}; /// /// let callsite: &'static CallSite = callsite!("here"); /// assert_eq!(callsite.name(), "here"); /// ``` #[macro_export] macro_rules! callsite { ($name: expr) => { { static CALL_SITE: $crate::Lazy<$crate::CallSite> = $crate::Lazy::new(|| { $crate::CallSite::new( $name, module_path!(), file!(), line!(), ) }); static REGISTRATION: $crate::Lazy<()> = $crate::Lazy::new(|| { $crate::register_callsite(&*CALL_SITE) }); $crate::Lazy::force(®ISTRATION); &*CALL_SITE } }; } /// Run a block of code inside a new span /// /// This macro creates a new [`CallSite`] with the given name at the current /// source location, and record the provided code execution by running it inside /// a [`Span`]. /// /// # Examples /// ``` /// use time_graph::spanned; /// /// let result = spanned!("named", { /// let first = 30; /// let second = 12; /// first + second /// }); /// /// assert_eq!(result, 42); /// ``` #[macro_export] macro_rules! spanned { ($name: expr, $block: expr) => { { let __tfg_callsite = $crate::callsite!($name); let __tfg_span = $crate::Span::new(__tfg_callsite); let __tfg_guard = __tfg_span.enter(); $block } } } mod callsite; pub use self::callsite::CallSite; pub(crate) use self::callsite::CallSiteId; pub use self::callsite::{register_callsite, traverse_registered_callsite}; mod graph; pub use self::graph::{Span, SpanGuard}; pub use self::graph::{get_full_graph, clear_collected_data, enable_data_collection}; pub use self::graph::{FullCallGraph, TimedSpan};