diff --git a/crates/codspeed/Cargo.toml b/crates/codspeed/Cargo.toml index b1f6c00a..91c573fa 100644 --- a/crates/codspeed/Cargo.toml +++ b/crates/codspeed/Cargo.toml @@ -22,12 +22,14 @@ anyhow = { workspace = true } colored = "2.0.0" glob = "0.3.2" libc = "^0.2" -nix = { version = "0.30.1", features = ["time"] } serde = { workspace = true } serde_json = { workspace = true } statrs = { version = "0.18.0", default-features = false } uuid = { version = "1.12.1", features = ["v4"] } +[target.'cfg(target_os = "linux")'.dependencies] +nix = { version = "0.30.1", features = ["time"] } + [[bench]] name = "native" harness = false diff --git a/crates/codspeed/build.rs b/crates/codspeed/build.rs index 22f58401..3eef6527 100644 --- a/crates/codspeed/build.rs +++ b/crates/codspeed/build.rs @@ -1,11 +1,6 @@ use std::{env, path::PathBuf}; fn main() { - if cfg!(not(target_os = "linux")) { - // The instrument-hooks library is only supported on Linux. - return; - } - // Compile the C library cc::Build::new() .file("instrument-hooks/dist/core.c") diff --git a/crates/codspeed/instrument-hooks b/crates/codspeed/instrument-hooks index b3d4b78e..b1e401a4 160000 --- a/crates/codspeed/instrument-hooks +++ b/crates/codspeed/instrument-hooks @@ -1 +1 @@ -Subproject commit b3d4b78ef68498d59afd45a9c8b2ef096652f034 +Subproject commit b1e401a4d031ad308edb22ed59a52253a1ebe924 diff --git a/crates/codspeed/src/instrument_hooks/mod.rs b/crates/codspeed/src/instrument_hooks/mod.rs index ef4e08c1..287b6762 100644 --- a/crates/codspeed/src/instrument_hooks/mod.rs +++ b/crates/codspeed/src/instrument_hooks/mod.rs @@ -1,180 +1,132 @@ -#[cfg(target_os = "linux")] -mod ffi; - -#[cfg(target_os = "linux")] -mod linux_impl { - use nix::sys::time::TimeValLike; +use std::ffi::CString; +use std::sync::OnceLock; - use super::ffi; - use std::ffi::CString; - use std::sync::OnceLock; +mod ffi; - pub struct InstrumentHooks(*mut ffi::InstrumentHooks); +pub struct InstrumentHooks(*mut ffi::InstrumentHooks); - unsafe impl Send for InstrumentHooks {} - unsafe impl Sync for InstrumentHooks {} +unsafe impl Send for InstrumentHooks {} +unsafe impl Sync for InstrumentHooks {} - impl InstrumentHooks { - #[inline(always)] - pub fn new() -> Option { - let ptr = unsafe { ffi::instrument_hooks_init() }; - if ptr.is_null() { - None - } else { - Some(InstrumentHooks(ptr)) - } +impl InstrumentHooks { + #[inline(always)] + pub fn new() -> Option { + let ptr = unsafe { ffi::instrument_hooks_init() }; + if ptr.is_null() { + None + } else { + Some(InstrumentHooks(ptr)) } + } - /// Returns a singleton instance of `InstrumentHooks`. - #[inline(always)] - pub fn instance() -> &'static Self { - static INSTANCE: OnceLock = OnceLock::new(); - INSTANCE.get_or_init(|| { - let instance = - InstrumentHooks::new().expect("Failed to initialize InstrumentHooks"); - instance - .set_integration("codspeed-rust", env!("CARGO_PKG_VERSION")) - .expect("Failed to set integration"); - instance - }) - } + /// Returns a singleton instance of `InstrumentHooks`. + #[inline(always)] + pub fn instance() -> &'static Self { + static INSTANCE: OnceLock = OnceLock::new(); + INSTANCE.get_or_init(|| { + let instance = InstrumentHooks::new().expect("Failed to initialize InstrumentHooks"); + instance + .set_integration("codspeed-rust", env!("CARGO_PKG_VERSION")) + .expect("Failed to set integration"); + instance + }) + } - #[inline(always)] - pub fn is_instrumented(&self) -> bool { - unsafe { ffi::instrument_hooks_is_instrumented(self.0) } - } + #[inline(always)] + pub fn is_instrumented(&self) -> bool { + unsafe { ffi::instrument_hooks_is_instrumented(self.0) } + } - #[inline(always)] - pub fn start_benchmark(&self) -> Result<(), i8> { - let result = unsafe { ffi::instrument_hooks_start_benchmark(self.0) }; - if result == 0 { - Ok(()) - } else { - Err(result) - } + #[inline(always)] + pub fn start_benchmark(&self) -> Result<(), u8> { + let result = unsafe { ffi::instrument_hooks_start_benchmark(self.0) }; + if result == 0 { + Ok(()) + } else { + Err(result) } + } - #[inline(always)] - pub fn stop_benchmark(&self) -> Result<(), i8> { - let result = unsafe { ffi::instrument_hooks_stop_benchmark(self.0) }; - if result == 0 { - Ok(()) - } else { - Err(result) - } + #[inline(always)] + pub fn stop_benchmark(&self) -> Result<(), u8> { + let result = unsafe { ffi::instrument_hooks_stop_benchmark(self.0) }; + if result == 0 { + Ok(()) + } else { + Err(result) } + } - #[inline(always)] - pub fn set_executed_benchmark(&self, uri: &str) -> Result<(), i8> { - let pid = std::process::id() as i32; - let c_uri = CString::new(uri).map_err(|_| -1i8)?; - let result = unsafe { - ffi::instrument_hooks_set_executed_benchmark(self.0, pid, c_uri.as_ptr()) - }; - if result == 0 { - Ok(()) - } else { - Err(result) - } + #[inline(always)] + pub fn set_executed_benchmark(&self, uri: &str) -> Result<(), u8> { + let pid = std::process::id() as i32; + let c_uri = CString::new(uri).map_err(|_| 1u8)?; + let result = + unsafe { ffi::instrument_hooks_set_executed_benchmark(self.0, pid, c_uri.as_ptr()) }; + if result == 0 { + Ok(()) + } else { + Err(result) } + } - #[inline(always)] - pub fn set_integration(&self, name: &str, version: &str) -> Result<(), i8> { - let c_name = CString::new(name).map_err(|_| -1i8)?; - let c_version = CString::new(version).map_err(|_| -1i8)?; - let result = unsafe { - ffi::instrument_hooks_set_integration(self.0, c_name.as_ptr(), c_version.as_ptr()) - }; - if result == 0 { - Ok(()) - } else { - Err(result) - } + #[inline(always)] + pub fn set_integration(&self, name: &str, version: &str) -> Result<(), u8> { + let c_name = CString::new(name).map_err(|_| 1u8)?; + let c_version = CString::new(version).map_err(|_| 1u8)?; + let result = unsafe { + ffi::instrument_hooks_set_integration(self.0, c_name.as_ptr(), c_version.as_ptr()) + }; + if result == 0 { + Ok(()) + } else { + Err(result) } + } - #[inline(always)] - pub fn add_benchmark_timestamps(&self, start: u64, end: u64) { - let pid = std::process::id(); - - unsafe { - ffi::instrument_hooks_add_marker( - self.0, - pid, - ffi::MARKER_TYPE_BENCHMARK_START as u8, - start, - ) - }; - unsafe { - ffi::instrument_hooks_add_marker( - self.0, - pid, - ffi::MARKER_TYPE_BENCHMARK_END as u8, - end, - ) - }; + #[inline(always)] + pub fn add_benchmark_timestamps(&self, start: u64, end: u64) { + let pid = std::process::id(); + + unsafe { + ffi::instrument_hooks_add_marker( + self.0, + pid, + ffi::MARKER_TYPE_BENCHMARK_START as u8, + start, + ) + }; + unsafe { + ffi::instrument_hooks_add_marker(self.0, pid, ffi::MARKER_TYPE_BENCHMARK_END as u8, end) + }; + } + + #[inline(always)] + pub fn current_timestamp() -> u64 { + #[cfg(not(target_os = "linux"))] + { + unsafe { ffi::instrument_hooks_current_timestamp() } } - #[inline(always)] - pub fn current_timestamp() -> u64 { + // Custom implementation to avoid the extra FFI call + #[cfg(target_os = "linux")] + { + use nix::sys::time::TimeValLike; nix::time::clock_gettime(nix::time::ClockId::CLOCK_MONOTONIC) .expect("Failed to get current time") .num_nanoseconds() as u64 } } - - impl Drop for InstrumentHooks { - fn drop(&mut self) { - if !self.0.is_null() { - unsafe { ffi::instrument_hooks_deinit(self.0) }; - } - } - } } -#[cfg(not(target_os = "linux"))] -mod other_impl { - pub struct InstrumentHooks; - - impl InstrumentHooks { - pub fn instance() -> &'static Self { - static INSTANCE: InstrumentHooks = InstrumentHooks; - &INSTANCE - } - - pub fn is_instrumented(&self) -> bool { - false - } - - pub fn start_benchmark(&self) -> Result<(), i8> { - Ok(()) - } - - pub fn stop_benchmark(&self) -> Result<(), i8> { - Ok(()) - } - - pub fn set_executed_benchmark(&self, _uri: &str) -> Result<(), i8> { - Ok(()) - } - - pub fn set_integration(&self, _name: &str, _version: &str) -> Result<(), i8> { - Ok(()) - } - - pub fn add_benchmark_timestamps(&self, _start: u64, _end: u64) {} - - pub fn current_timestamp() -> u64 { - 0 +impl Drop for InstrumentHooks { + fn drop(&mut self) { + if !self.0.is_null() { + unsafe { ffi::instrument_hooks_deinit(self.0) }; } } } -#[cfg(target_os = "linux")] -pub use linux_impl::InstrumentHooks; - -#[cfg(not(target_os = "linux"))] -pub use other_impl::InstrumentHooks; - #[cfg(test)] mod tests { use super::InstrumentHooks;