//! Timers, memory measurement and the hash function used by the tables. use std::hash::{BuildHasherDefault, Hasher}; /// CPU time consumed by the calling thread (seconds), via CLOCK_THREAD_CPUTIME_ID. pub fn thread_cpu_s() -> f64 { let mut ts = libc::timespec { tv_sec: 0, tv_nsec: 0 }; unsafe { libc::clock_gettime(libc::CLOCK_THREAD_CPUTIME_ID, &mut ts); } ts.tv_sec as f64 + ts.tv_nsec as f64 * 1e-9 } /// Process CPU time (user + system) via getrusage. pub fn process_cpu_s() -> f64 { let mut ru: libc::rusage = unsafe { std::mem::zeroed() }; unsafe { libc::getrusage(libc::RUSAGE_SELF, &mut ru); } let tv = |t: libc::timeval| t.tv_sec as f64 + t.tv_usec as f64 * 1e-6; tv(ru.ru_utime) + tv(ru.ru_stime) } /// Peak resident set size in bytes (ru_maxrss is bytes on macOS, kilobytes on Linux). pub fn peak_rss_bytes() -> u64 { let mut ru: libc::rusage = unsafe { std::mem::zeroed() }; unsafe { libc::getrusage(libc::RUSAGE_SELF, &mut ru); } let v = ru.ru_maxrss as u64; if cfg!(target_os = "macos") { v } else { v * 1024 } } /// Cheap multiplicative hasher for u64 keys that are already well-mixed field residues. #[derive(Default, Clone, Copy)] pub struct FxHasher { h: u64, } impl Hasher for FxHasher { #[inline(always)] fn finish(&self) -> u64 { self.h } #[inline(always)] fn write(&mut self, bytes: &[u8]) { for b in bytes { self.h = (self.h.rotate_left(5) ^ (*b as u64)).wrapping_mul(0x517cc1b727220a95); } } #[inline(always)] fn write_u64(&mut self, i: u64) { let z = i.wrapping_mul(0x9E3779B97F4A7C15); self.h = z ^ (z >> 32); } } pub type FxBuild = BuildHasherDefault;