#![allow(dead_code)]
pub const N: usize = 44;
#[rustfmt::skip]
pub static NAMES: [&str; N] = [
"decode:read", "decode:codec", "decode:reduce", "decode:fit",
"thumb", "sift:base", "sift:blur", "sift:extrema", "sift:grad",
"sift:describe", "sift:sort",
"quantise", "vocab", "invfile", "query", "shared", "correspond",
"best_transform", "encloses", "overlap", "pixel_check", "propagate",
"decode:jpeg", "decode:png", "decode:webp", "decode:tiff", "decode:jxl",
"decode:heif",
"group",
"decode:permit", "sift:ori", "sift:desc", "sift:halve",
"main:exact", "main:pool", "main:candsort", "main:output", "main:release",
"variant:pass", "variant:quantise", "variant:mkfeats", "cand:rank",
"verify:direct",
"pixel_check:prop",
];
pub static ACC: [std::sync::atomic::AtomicU64; N] =
[const { std::sync::atomic::AtomicU64::new(0) }; N];
#[cfg(feature = "prof")]
#[inline(always)]
pub fn cycles() -> u64 {
#[cfg(target_arch = "x86_64")]
{
unsafe { core::arch::x86_64::_rdtsc() }
}
#[cfg(not(target_arch = "x86_64"))]
{
std::time::Instant::now().elapsed().as_nanos() as u64
}
}
#[cfg(feature = "prof")]
static EPOCH: std::sync::OnceLock<(std::time::Instant, u64)> = std::sync::OnceLock::new();
pub fn start() {
#[cfg(feature = "prof")]
{
let _ = EPOCH.set((std::time::Instant::now(), cycles()));
}
}
#[macro_export]
macro_rules! timed {
($i:expr, $body:expr) => {{
#[cfg(feature = "prof")]
{
let t = $crate::prof::cycles();
let r = $body;
$crate::prof::ACC[$i].fetch_add(
$crate::prof::cycles().wrapping_sub(t),
std::sync::atomic::Ordering::Relaxed,
);
r
}
#[cfg(not(feature = "prof"))]
{
$body
}
}};
}
pub fn report() {
#[cfg(feature = "prof")]
{
let hz = match EPOCH.get() {
Some(&(t0, c0)) => {
let secs = t0.elapsed().as_secs_f64();
let ticks = cycles().wrapping_sub(c0) as f64;
if secs > 0.05 { ticks / secs } else { 1e9 }
}
None => 1e9,
};
let mut v: Vec<(f64, &str)> = NAMES
.iter()
.enumerate()
.map(|(i, n)| (ACC[i].load(std::sync::atomic::Ordering::Relaxed) as f64 / hz, *n))
.filter(|(t, _)| *t > 0.0)
.collect();
v.sort_by(|a, b| b.0.partial_cmp(&a.0).unwrap());
eprintln!("--- profile (cpu seconds; stages nest; tsc {:.0} MHz) ---", hz / 1e6);
for (t, n) in v {
eprintln!("{n:>18} {t:8.2}");
}
}
}