canic_core/macros/
perf.rs

1/// Log elapsed instruction counts since the last `perf!` invocation.
2///
3/// Records the delta in instructions between calls and emits a
4/// [`Log::Perf`](crate::Log::Perf)
5/// entry with the provided label (any tokens accepted by `format!`). Use this
6/// to highlight hot paths in long-running maintenance tasks.
7#[macro_export]
8macro_rules! perf {
9    ($($label:tt)*) => {{
10        $crate::perf::PERF_LAST.with(|last| {
11            let now = $crate::cdk::api::performance_counter(1);
12            let then = *last.borrow();
13            let delta = now.saturating_sub(then);
14            *last.borrow_mut() = now;
15
16            let label = format!($($label)*);
17            let delta_fmt = $crate::utils::instructions::format_instructions(delta);
18            let now_fmt = $crate::utils::instructions::format_instructions(now);
19
20            $crate::perf::record(&label, delta);
21            $crate::cdk::println!(
22                "{}: '{}' used {}i since last (total: {}i)",
23                module_path!(),
24                label,
25                delta_fmt,
26                now_fmt
27            );
28        });
29    }};
30}
31
32/// Record a single-call instruction counter snapshot when the surrounding
33/// scope exits.
34///
35/// Expands to a `defer!` guard that logs the total instructions consumed in
36/// the enclosing scope, tagged as [`Log::Perf`](crate::Log::Perf). Pair this
37/// with manual checkpoints logged via [`macro@perf`] to track both cumulative and incremental
38/// usage.
39#[macro_export]
40macro_rules! perf_defer {
41    () => {
42        $crate::export::defer::defer!({
43            let end = $crate::cdk::api::performance_counter(1);
44            let end_fmt = $crate::utils::instructions::format_instructions(end);
45
46            $crate::cdk::println!("{} used {}i in this call", module_path!(), end_fmt,)
47        });
48    };
49}