timing_rdtsc 0.1.2

Easily time a block of code
Documentation
use std::arch::asm;
use std::time::{Duration, Instant};

pub fn timing<F: FnOnce()>(f: F) -> Duration {
    let start = Instant::now();
    f();
    start.elapsed()
}

pub fn timing_return<T, F: FnOnce() -> T>(f: F) -> (T, Duration) {
    let start = Instant::now();
    let t = f();
    (t, start.elapsed())
}

#[cfg(target_arch = "x86_64")]
#[inline]
fn rdtsc_start() -> u64 {
    let rax: u64;
    unsafe {
        asm!(
            "mfence",
            "lfence",
            "rdtsc",
            "shl rdx, 32",
            "or rax, rdx",
            out("rax") rax
        );
    }
    rax
}

#[cfg(target_arch = "x86_64")]
#[inline]
fn rdtsc_stop() -> u64 {
    let rax: u64;
    unsafe {
        asm!(
            "rdtsc",
            "lfence",
            "shl rdx, 32",
            "or rax, rdx",
            out("rax") rax
        );
    }
    rax
}

#[cfg(target_arch = "x86_64")]
pub fn timing_rdtsc<F: FnOnce()>(f: F) -> u64 {
    let start = rdtsc_start();
    f();
    let end = rdtsc_stop();
    end - start
}

#[cfg(target_arch = "x86_64")]
pub fn timing_rdtsc_return<T, F: FnOnce() -> T>(f: F) -> (T, u64) {
    let start = rdtsc_start();
    let t = f();
    let end = rdtsc_stop();
    (t, end - start)
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn simple_timing() {
        let time = timing(|| {
            println!("A fn that takes a few micros");
        });

        assert!(!time.is_zero());
    }

    #[test]
    fn simple_timing_with_return() {
        let (val, time) = timing_return(|| {
            println!("A fn that takes a few micros");
            5
        });

        assert!(!time.is_zero());
        assert!(val == 5);
    }

    #[test]
    fn rdtsc_timing() {
        let counter = timing_rdtsc(|| {
            println!("...");
        });

        assert!(counter != 0);
        println!("{counter}");
    }

    #[test]
    fn rdtsc_timing_return() {
        let (val, counter) = timing_rdtsc_return(|| {
            println!("...");
            42
        });

        assert!(counter != 0);
        assert!(val == 42);
    }
}