diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7b235ac1..38dbd614 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,10 +11,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: Swatinem/rust-cache@v2 - - uses: actions-rs/toolchain@v1 + - uses: moonrepo/setup-rust@v0 with: - toolchain: stable + channel: stable components: clippy - uses: pre-commit/action@v2.0.0 with: @@ -24,20 +23,20 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: Swatinem/rust-cache@v2 - - uses: actions-rs/toolchain@v1 + - uses: moonrepo/setup-rust@v0 with: - toolchain: stable + channel: stable - run: cargo test --all compat-integration-test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: actions-rs/toolchain@v1 + - uses: moonrepo/setup-rust@v0 with: - toolchain: stable - - uses: Swatinem/rust-cache@v2 + channel: stable + cache-target: release + - run: cargo install --path crates/cargo-codspeed - run: cargo codspeed build -p codspeed diff --git a/Cargo.lock b/Cargo.lock index f85d68ca..b9801055 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -78,7 +78,7 @@ dependencies = [ "async-lock", "async-task", "concurrent-queue", - "fastrand", + "fastrand 1.8.0", "futures-lite", "slab", ] @@ -276,7 +276,7 @@ dependencies = [ "async-lock", "async-task", "atomic-waker", - "fastrand", + "fastrand 1.8.0", "futures-lite", "log", ] @@ -515,7 +515,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.105", ] [[package]] @@ -542,6 +542,8 @@ version = "2.0.0" dependencies = [ "colored", "libc", + "serde_json", + "tempfile", ] [[package]] @@ -754,7 +756,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" dependencies = [ "quote", - "syn", + "syn 1.0.105", ] [[package]] @@ -855,6 +857,12 @@ dependencies = [ "instant", ] +[[package]] +name = "fastrand" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" + [[package]] name = "filetime" version = "0.2.18" @@ -863,7 +871,7 @@ checksum = "4b9663d381d07ae25dc88dbdf27df458faa83a9b25336bcac83d5e452b5fc9d3" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.2.16", "windows-sys 0.42.0", ] @@ -977,7 +985,7 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" dependencies = [ - "fastrand", + "fastrand 1.8.0", "futures-core", "futures-io", "memchr", @@ -1505,7 +1513,7 @@ checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.105", ] [[package]] @@ -1663,7 +1671,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", - "syn", + "syn 1.0.105", "version_check", ] @@ -1680,18 +1688,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.47" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.21" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" dependencies = [ "proc-macro2", ] @@ -1742,6 +1750,15 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "regex" version = "1.7.0" @@ -1765,15 +1782,6 @@ version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" -[[package]] -name = "remove_dir_all" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] - [[package]] name = "rustc-demangle" version = "0.1.23" @@ -1867,22 +1875,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.151" +version = "1.0.176" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fed41fc1a24994d044e6db6935e69511a1153b52c15eb42493b26fa87feba0" +checksum = "76dc28c9523c5d70816e393136b86d48909cfb27cecaa902d338c19ed47164dc" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.151" +version = "1.0.176" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "255abe9a125a985c05190d687b320c12f9b1f0b99445e608c21ba0782c719ad8" +checksum = "a4e7b8c5dc823e3b90651ff1d3808419cd14e5ad76de04feaf37da114e7a306f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.27", ] [[package]] @@ -1896,9 +1904,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.91" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" +checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c" dependencies = [ "itoa", "ryu", @@ -2008,6 +2016,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "2.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b60f673f44a8255b9c8c657daf66a596d435f2da81a555b06dc644d080ba45e0" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "tar" version = "0.4.38" @@ -2020,16 +2039,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.3.0" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +checksum = "5486094ee78b2e5038a6382ed7645bc084dc2ec433426ca4c3cb61e2007b8998" dependencies = [ "cfg-if", - "fastrand", - "libc", - "redox_syscall", - "remove_dir_all", - "winapi", + "fastrand 2.0.0", + "redox_syscall 0.3.5", + "rustix 0.38.4", + "windows-sys 0.48.0", ] [[package]] @@ -2272,7 +2290,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn", + "syn 1.0.105", "wasm-bindgen-shared", ] @@ -2306,7 +2324,7 @@ checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.105", "wasm-bindgen-backend", "wasm-bindgen-shared", ] diff --git a/crates/bencher_compat/benches/bencher_example.rs b/crates/bencher_compat/benches/bencher_example.rs index 8613da52..c1be9bfc 100644 --- a/crates/bencher_compat/benches/bencher_example.rs +++ b/crates/bencher_compat/benches/bencher_example.rs @@ -12,5 +12,20 @@ pub fn b(bench: &mut Bencher) { bench.bytes = N as u64; } -benchmark_group!(benches, a, b); +mod c { + use super::*; + + pub fn a(bench: &mut Bencher) { + bench.iter(|| (0..100).fold(0, |x, y| black_box(x + y))) + } + + pub fn b(bench: &mut Bencher) { + const N: usize = 1024; + bench.iter(|| vec![0u8; N]); + + bench.bytes = N as u64; + } +} + +benchmark_group!(benches, a, b, c::a, c::b); benchmark_main!(benches); diff --git a/crates/bencher_compat/src/compat.rs b/crates/bencher_compat/src/compat.rs index 9cbd8aa6..76a76033 100644 --- a/crates/bencher_compat/src/compat.rs +++ b/crates/bencher_compat/src/compat.rs @@ -1,14 +1,22 @@ -use codspeed::codspeed::{black_box, CodSpeed, WARMUP_RUNS}; +use codspeed::{ + codspeed::{black_box, CodSpeed, WARMUP_RUNS}, + utils::{get_formated_function_path, get_git_relative_path}, +}; pub struct Bencher { pub bytes: u64, codspeed: CodSpeed, - current_uri: String, + current_file: String, + current_bench_path: String, } impl Bencher { - pub fn set_current_uri(&mut self, uri: String) { - self.current_uri = uri; + pub fn set_current_file(&mut self, file: impl Into) { + self.current_file = file.into(); + } + + pub fn set_current_bench_path(&mut self, bench: impl Into) { + self.current_bench_path = bench.into(); } pub fn push_group(&mut self, group: &str) { @@ -23,11 +31,13 @@ impl Bencher { where F: FnMut() -> T, { - let uri = self.current_uri.as_str(); + let file = get_git_relative_path(self.current_file.as_str()); + let bench_path = get_formated_function_path(self.current_bench_path.as_str()); + let uri = format!("{}::{}", file.to_string_lossy(), bench_path); for _ in 0..WARMUP_RUNS { black_box(inner()); } - self.codspeed.start_benchmark(uri); + self.codspeed.start_benchmark(uri.as_str()); black_box(inner()); self.codspeed.end_benchmark(); } @@ -42,18 +52,20 @@ impl Default for Bencher { Bencher { bytes: 0, codspeed: CodSpeed::new(), - current_uri: String::new(), + current_file: String::new(), + current_bench_path: String::new(), } } } #[macro_export] macro_rules! benchmark_group { - ($group_name:ident, $($function:path),+) => { + ($group_name:ident, $( $function:path ),+ $(,)*) => { pub fn $group_name(bencher: &mut $crate::Bencher) { bencher.push_group(stringify!($group_name)); $( - bencher.set_current_uri($crate::codspeed_uri!($function)); + bencher.set_current_file($crate::abs_file!()); + bencher.set_current_bench_path(stringify!($function)); $function(bencher); )+ bencher.pop_group(); diff --git a/crates/bencher_compat/src/lib.rs b/crates/bencher_compat/src/lib.rs index ab34f19f..628c23cd 100644 --- a/crates/bencher_compat/src/lib.rs +++ b/crates/bencher_compat/src/lib.rs @@ -1,5 +1,3 @@ -pub use codspeed::codspeed_uri; - #[cfg(not(codspeed))] mod compat_bencher { pub use bencher::*; @@ -8,6 +6,8 @@ mod compat_bencher { #[cfg(codspeed)] #[path = "."] mod compat_bencher { + pub use codspeed::abs_file; + mod compat; pub use compat::*; } diff --git a/crates/cargo-codspeed/src/run.rs b/crates/cargo-codspeed/src/run.rs index 1f1ec850..de0f34a2 100644 --- a/crates/cargo-codspeed/src/run.rs +++ b/crates/cargo-codspeed/src/run.rs @@ -67,12 +67,26 @@ pub fn run_benches( )?; for bench in to_run.iter() { let bench_name = bench.file_name().unwrap().to_str().unwrap(); + // workspace_root is needed since file! returns the path relatively to the workspace root + // while CARGO_MANIFEST_DIR returns the path to the sub package + let workspace_root = ws.root().to_string_lossy(); ws.config() .shell() .status_with_color("Running", bench_name, Color::Yellow)?; std::process::Command::new(bench) + .env("CODSPEED_CARGO_WORKSPACE_ROOT", workspace_root.as_ref()) .status() - .map_err(|_| anyhow!("failed to execute the benchmark process"))?; + .map_err(|_| anyhow!("failed to execute the benchmark process")) + .and_then(|status| { + if status.success() { + Ok(()) + } else { + Err(anyhow!( + "failed to execute the benchmark process, exit code: {}", + status.code().unwrap_or(1) + )) + } + })?; ws.config().shell().status_with_color( "Done", format!("running {}", bench_name), diff --git a/crates/codspeed/Cargo.toml b/crates/codspeed/Cargo.toml index 03431a55..54505c64 100644 --- a/crates/codspeed/Cargo.toml +++ b/crates/codspeed/Cargo.toml @@ -19,7 +19,11 @@ keywords = ["codspeed", "benchmark"] [dependencies] colored = "2.0.0" libc = "^0.2" +serde_json = "1.0.104" [[bench]] name = "native" harness = false + +[dev-dependencies] +tempfile = "3.7.0" diff --git a/crates/codspeed/src/lib.rs b/crates/codspeed/src/lib.rs index b1b345dd..42ffe4be 100644 --- a/crates/codspeed/src/lib.rs +++ b/crates/codspeed/src/lib.rs @@ -2,3 +2,4 @@ pub mod codspeed; mod macros; mod measurement; mod request; +pub mod utils; diff --git a/crates/codspeed/src/macros.rs b/crates/codspeed/src/macros.rs index 954e6c0d..df8414ab 100644 --- a/crates/codspeed/src/macros.rs +++ b/crates/codspeed/src/macros.rs @@ -1,3 +1,15 @@ +#[macro_export] +macro_rules! abs_file { + () => { + std::path::PathBuf::from( + std::env::var("CODSPEED_CARGO_WORKSPACE_ROOT") + .expect("Could not find CODSPEED_CARGO_WORKSPACE_ROOT env variable, make sure you are using the latest version of cargo-codspeed") + ) + .join(file!()) + .to_string_lossy() + }; +} + #[macro_export] macro_rules! codspeed_uri { ( $name:ident ) => { diff --git a/crates/codspeed/src/utils.rs b/crates/codspeed/src/utils.rs new file mode 100644 index 00000000..d9cc1a49 --- /dev/null +++ b/crates/codspeed/src/utils.rs @@ -0,0 +1,71 @@ +use std::io; +use std::path::{Path, PathBuf}; + +fn get_parent_git_repo_path(abs_path: &Path) -> io::Result { + if abs_path.join(".git").exists() { + Ok(abs_path.to_path_buf()) + } else { + get_parent_git_repo_path( + abs_path + .parent() + .ok_or(io::Error::from(io::ErrorKind::NotFound))?, + ) + } +} + +pub fn get_git_relative_path

(abs_path: P) -> PathBuf +where + P: AsRef, +{ + let abs_path = abs_path.as_ref(); + match abs_path + .canonicalize() + .and_then(|p| get_parent_git_repo_path(&p)) + { + Ok(repo_path) => abs_path.strip_prefix(repo_path).unwrap().to_path_buf(), + Err(_) => abs_path.to_path_buf(), + } +} + +/// Fixes spaces around `::` created by stringify!($function). +pub fn get_formated_function_path(function_path: impl Into) -> String { + let function_path = function_path.into(); + function_path.replace(" :: ", "::") +} + +#[cfg(test)] +mod tests { + use super::*; + use std::fs; + use tempfile::tempdir; + + #[test] + fn test_get_git_relative_path_found() { + // Create a temp directory. + let dir = tempdir().unwrap(); + let git_dir = dir.path().join(".git"); + fs::create_dir(git_dir).unwrap(); + let nested_dir = dir.path().join("folder").join("nested_folder"); + fs::create_dir_all(&nested_dir).unwrap(); + + let relative_path = get_git_relative_path(&nested_dir); + assert_eq!(relative_path, PathBuf::from("folder/nested_folder")); + } + + #[test] + fn test_get_git_relative_path_not_found() { + let dir = tempdir().unwrap(); + let path_dir = dir.path().join("folder"); + fs::create_dir_all(&path_dir).unwrap(); + + let relative_path = get_git_relative_path(&path_dir); + assert_eq!(relative_path, path_dir.canonicalize().unwrap()); + } + + #[test] + fn test_get_formated_function_path() { + let input = "std :: vec :: Vec :: new"; + let expected_output = "std::vec::Vec::new".to_string(); + assert_eq!(get_formated_function_path(input), expected_output); + } +} diff --git a/crates/criterion_compat/benches/test_benches.rs b/crates/criterion_compat/benches/test_benches.rs index bd9b7994..8d84e24e 100644 --- a/crates/criterion_compat/benches/test_benches.rs +++ b/crates/criterion_compat/benches/test_benches.rs @@ -14,5 +14,22 @@ fn bench(c: &mut Criterion) { }); } -criterion_group!(benches, bench); +mod nested { + use super::*; + pub fn bench(c: &mut Criterion) { + // Setup (construct data, allocate memory, etc) + let input = 5u64; + c.bench_with_input(BenchmarkId::new("with_input", input), &input, |b, i| { + b.iter(|| { + let mut x = 0; + for _ in 0..*i { + x += 2; + } + x + }) + }); + } +} + +criterion_group!(benches, bench, nested::bench); criterion_main!(benches); diff --git a/crates/criterion_compat/src/compat/group.rs b/crates/criterion_compat/src/compat/group.rs index 1208d997..88a8d3f8 100644 --- a/crates/criterion_compat/src/compat/group.rs +++ b/crates/criterion_compat/src/compat/group.rs @@ -1,6 +1,6 @@ use std::{cell::RefCell, rc::Rc, time::Duration}; -use codspeed::codspeed::CodSpeed; +use codspeed::{codspeed::CodSpeed, utils::get_git_relative_path}; use criterion::{measurement::Measurement, SamplingMode, Throughput}; use crate::{Bencher, Criterion}; @@ -53,9 +53,12 @@ impl BenchmarkGroup { F: FnMut(&mut Bencher, &I), I: ?Sized, { + let git_relative_file_path = get_git_relative_path(&self.current_file); let mut uri = format!( "{}::{}::{}", - self.current_file, self.macro_group, self.group_name, + git_relative_file_path.to_string_lossy(), + self.macro_group, + self.group_name, ); if let Some(function_name) = id.function_name { uri = format!("{}::{}", uri, function_name); diff --git a/crates/criterion_compat/src/compat/macros.rs b/crates/criterion_compat/src/compat/macros.rs index 7be8ce69..495dea4c 100644 --- a/crates/criterion_compat/src/compat/macros.rs +++ b/crates/criterion_compat/src/compat/macros.rs @@ -4,7 +4,7 @@ macro_rules! criterion_group { pub fn $name(criterion: &mut $crate::Criterion) { let mut criterion = &mut criterion.with_patched_measurement($config); $( - criterion.set_current_file(file!()); + criterion.set_current_file($crate::abs_file!()); criterion.set_macro_group(format!("{}::{}", stringify!($name), stringify!($target))); $target(criterion); )+ diff --git a/crates/criterion_compat/src/lib.rs b/crates/criterion_compat/src/lib.rs index d5d1be9c..4c36258e 100644 --- a/crates/criterion_compat/src/lib.rs +++ b/crates/criterion_compat/src/lib.rs @@ -8,6 +8,8 @@ mod compat_criterion { #[cfg(codspeed)] #[path = "."] mod compat_criterion { + pub use codspeed::abs_file; + mod compat; pub use compat::*;