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 delta_fmt = $crate::utils::instructions::format_instructions(delta);
17            let now_fmt = $crate::utils::instructions::format_instructions(now);
18
19            $crate::cdk::println!(
20                "{}: '{}' used {}i since last (total: {}i)",
21                module_path!(),
22                format!($($label)*),
23                delta_fmt,
24                now_fmt
25            );
26        });
27    }};
28}
29
30/// Record a single-call instruction counter snapshot when the surrounding
31/// scope exits.
32///
33/// Expands to a `defer!` guard that logs the total instructions consumed in
34/// the enclosing scope, tagged as [`Log::Perf`](crate::Log::Perf). Pair this
35/// with manual checkpoints logged via [`macro@perf`] to track both cumulative and incremental
36/// usage.
37#[macro_export]
38macro_rules! perf_start {
39    () => {
40        $crate::export::defer::defer!({
41            let end = $crate::cdk::api::performance_counter(1);
42            let end_fmt = $crate::utils::instructions::format_instructions(end);
43
44            $crate::cdk::println!("{} used {}i in this call", module_path!(), end_fmt,)
45        });
46    };
47}