use std::sync::OnceLock;
use std::time::Instant;
fn enabled() -> bool {
static ENABLED: OnceLock<bool> = OnceLock::new();
*ENABLED.get_or_init(|| {
std::env::var("MANIFOLD_TIMING").map_or(false, |v| !v.is_empty())
})
}
pub(crate) fn start() -> Option<Instant> {
if enabled() {
Some(Instant::now())
} else {
None
}
}
#[derive(Clone, Copy)]
pub(crate) struct Stopwatch {
#[cfg(not(target_arch = "wasm32"))]
t0: Instant,
}
impl Stopwatch {
#[inline]
pub fn start() -> Self {
Stopwatch {
#[cfg(not(target_arch = "wasm32"))]
t0: Instant::now(),
}
}
#[inline]
pub fn elapsed_ns(self) -> u64 {
#[cfg(not(target_arch = "wasm32"))]
{
self.t0.elapsed().as_nanos() as u64
}
#[cfg(target_arch = "wasm32")]
{
0
}
}
#[inline]
pub fn elapsed_secs(self) -> f64 {
#[cfg(not(target_arch = "wasm32"))]
{
self.t0.elapsed().as_secs_f64()
}
#[cfg(target_arch = "wasm32")]
{
0.0
}
}
}
pub type MemHook = fn() -> (usize, usize);
static MEM_HOOK: OnceLock<MemHook> = OnceLock::new();
pub fn set_mem_hook(hook: MemHook) {
let _ = MEM_HOOK.set(hook);
}
pub(crate) fn print_count(label: &str) {
if enabled() {
eprintln!("{label}");
}
}
pub(crate) fn print(label: &str, t0: Option<Instant>) {
if let Some(t0) = t0 {
match MEM_HOOK.get() {
Some(hook) => {
let (current, peak) = hook();
eprintln!(
"{}: {} sec, current = {:.1} MB, stage peak = {:.1} MB",
label,
t0.elapsed().as_secs_f64(),
current as f64 / 1048576.0,
peak as f64 / 1048576.0
);
}
None => eprintln!("{}: {} sec", label, t0.elapsed().as_secs_f64()),
}
}
}