precision 0.1.17

Low overhead, high precision measurement crate
Documentation
#[cfg(asm)]
#[allow(unused_imports)]
use core::arch::asm;

#[cfg(all(
    any(target_arch = "wasm32", target_arch = "wasm64"),
    target_os = "unknown"
))]
use wasm_bindgen::prelude::*;

use super::timestamp::*;

pub(crate) struct CPUCounter;

#[cfg(asm)]
#[inline]
#[cfg(target_arch = "x86_64")]
unsafe fn cpucounter() -> u64 {
    let (low, high): (u64, u64);
    asm!("rdtscp", out("eax") low, out("edx") high, out("ecx") _);
    (high << 32) | low
}

#[cfg(asm)]
#[inline]
#[cfg(target_arch = "x86")]
unsafe fn cpucounter() -> u64 {
    let (low, high): (u32, u32);
    asm!("rdtscp", out("eax") low, out("edx") high, out("ecx") _);
    ((high as u64) << 32) | (low as u64)
}

#[cfg(asm)]
#[inline]
#[cfg(target_arch = "aarch64")]
unsafe fn cpucounter() -> u64 {
    let vtm: u64;
    asm!("mrs {}, cntvct_el0", out(reg) vtm);
    vtm
}

#[cfg(asm)]
#[inline]
#[cfg(target_arch = "riscv64")]
unsafe fn cpucounter() -> u64 {
    let time: u64;
    asm!("rdtime {}", out(reg) time);
    time
}

#[cfg(all(not(asm), not(any(target_arch = "wasm32", target_arch = "wasm64"))))]
extern "C" {
    fn cpucounter() -> u64;
}

#[cfg(any(
    target_os = "wasix",
    all(target_os = "wasi", not(feature = "wasi-abi2"))
))]
#[inline]
fn cpucounter() -> u64 {
    use wasix::{clock_time_get, CLOCKID_MONOTONIC, CLOCKID_REALTIME};
    unsafe { clock_time_get(CLOCKID_MONOTONIC, 1_000_000) }
        .or_else(|_| unsafe { clock_time_get(CLOCKID_REALTIME, 1_000_000) })
        .expect("Clock not available")
}

#[cfg(all(target_os = "wasi", feature = "wasi-abi2"))]
fn cpucounter() -> u64 {
    let nsec = wasi_abi2::clocks::monotonic_clock::now();
    nsec
}

#[cfg(all(
    any(target_arch = "wasm32", target_arch = "wasm64"),
    target_os = "unknown"
))]
#[wasm_bindgen]
extern "C" {
    #[allow(non_camel_case_types)]
    type performance;

    #[wasm_bindgen(static_method_of = performance)]
    pub fn now() -> f64;
}

#[cfg(all(
    any(target_arch = "wasm32", target_arch = "wasm64"),
    target_os = "unknown"
))]
fn cpucounter() -> u64 {
    (performance::now() * 1_000_000.0) as u64
}

impl CPUCounter {
    #[inline]
    pub fn current() -> Timestamp {
        #[allow(unused_unsafe)]
        Timestamp(unsafe { cpucounter() })
    }
}