Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,16 @@ jobs:
- name: Install memtrack
run: |
cargo install --path crates/memtrack --locked
echo "CODSPEED_MEMTRACK_BINARY=$(which codspeed-memtrack)" >> $GITHUB_ENV

- run: cargo test --all --exclude memtrack
- run: cargo test --all --exclude memtrack --exclude exec-harness

exec-harness-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: moonrepo/setup-rust@v1
- name: Run tests
run: cargo test -p exec-harness

bpf-tests:
runs-on: ubuntu-latest
Expand Down
33 changes: 23 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 8 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ itertools = { workspace = true }
lazy_static = "1.4.0"
log = { workspace = true }
rand = "0.8.5"
rayon = "1.10"
regex = "1.10.2"
semver = "1.0"
reqwest = { version = "0.11.22", features = [
Expand All @@ -39,7 +40,7 @@ async-compression = { version = "0.4.5", features = ["tokio", "gzip"] }
simplelog = { version = "0.12.1", default-features = false, features = [
"termcolor",
] }
tempfile = "3.10.0"
tempfile = { workspace = true }
git2 = "0.20.2"
nestify = "0.3.3"
gql_client = { git = "https://github.com/CodSpeedHQ/gql-client-rs" }
Expand All @@ -51,13 +52,16 @@ async-trait = "0.1.82"
libc = { workspace = true }
bincode = "1.3.3"
object = "0.36.7"
linux-perf-data = "0.11.0"
linux-perf-data = { git = "https://github.com/CodSpeedHQ/linux-perf-data.git", rev = "e8c0ed51c2762b660708f8086e76a28449ef976c", features = [
"zstd",
] } # feat: support zstd compressed records
debugid = "0.8.0"
memmap2 = "0.9.5"
nix = { version = "0.29.0", features = ["fs", "time", "user"] }
futures = "0.3.31"
runner-shared = { path = "crates/runner-shared" }
memtrack = { path = "crates/memtrack", default-features = false }
exec-harness = { path = "crates/exec-harness" }
ipc-channel = "0.18"
shellexpand = { version = "3.1.1", features = ["tilde"] }
addr2line = "0.25"
Expand All @@ -84,14 +88,15 @@ members = ["crates/runner-shared", "crates/memtrack", "crates/exec-harness"]

[workspace.dependencies]
anyhow = "1.0"
clap = { version = "4.5", features = ["derive"] }
clap = { version = "4.5", features = ["derive", "env"] }
libc = "0.2"
log = "0.4.28"
serde_json = "1.0"
serde = { version = "1.0.228", features = ["derive"] }
ipc-channel = "0.18"
itertools = "0.14.0"
env_logger = "0.11.8"
tempfile = "3.10.0"

[workspace.metadata.release]
sign-tag = true
Expand Down
15 changes: 15 additions & 0 deletions crates/exec-harness/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,27 @@ edition = "2024"
repository = "https://github.com/CodSpeedHQ/runner"
publish = false

[lib]
name = "exec_harness"
path = "src/lib.rs"

[[bin]]
name = "exec-harness"
path = "src/main.rs"

[dependencies]
anyhow = { workspace = true }
codspeed = "4.1.0"
log = { workspace = true }
env_logger = { workspace = true }
clap = { workspace = true }
serde_json = { workspace = true }
serde = { workspace = true }
humantime = "2.1"
runner-shared = { path = "../runner-shared" }

[dev-dependencies]
tempfile = { workspace = true }

[package.metadata.dist]
targets = ["aarch64-unknown-linux-musl", "x86_64-unknown-linux-musl"]
7 changes: 7 additions & 0 deletions crates/exec-harness/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//! CodSpeed exec-harness library
//!
//! This library provides the core functionality for wrapping commands
//! with CodSpeed performance instrumentation.

mod prelude;
pub mod walltime;
54 changes: 16 additions & 38 deletions crates/exec-harness/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
use crate::prelude::*;
use crate::walltime::WalltimeResults;
use anyhow::Context;
use anyhow::Result;
use anyhow::bail;
use clap::Parser;
use codspeed::instrument_hooks::InstrumentHooks;
use codspeed::walltime_results::WalltimeBenchmark;
use runner_shared::walltime_results::WalltimeBenchmark;
use std::path::PathBuf;
use std::process;

mod prelude;
mod walltime;

#[derive(Parser, Debug)]
Expand All @@ -21,11 +19,19 @@ struct Args {
#[arg(long)]
name: Option<String>,

#[command(flatten)]
execution_args: walltime::WalltimeExecutionArgs,

/// The command and arguments to execute
command: Vec<String>,
}

fn main() -> Result<()> {
env_logger::builder()
.parse_env(env_logger::Env::new().filter_or("CODSPEED_LOG", "info"))
.format_timestamp(None)
.init();

let args = Args::parse();

if args.command.is_empty() {
Expand All @@ -49,46 +55,18 @@ fn main() -> Result<()> {
.set_integration("codspeed-rust", env!("CARGO_PKG_VERSION"))
.unwrap();

const NUM_ITERATIONS: usize = 1;
let mut times_per_round_ns = Vec::with_capacity(NUM_ITERATIONS);

hooks.start_benchmark().unwrap();
for _ in 0..NUM_ITERATIONS {
// Spawn the command
let mut child = process::Command::new(&args.command[0])
.args(&args.command[1..])
.spawn()
.context("Failed to spawn command")?;

// Start monotonic timer for this iteration
let bench_start = InstrumentHooks::current_timestamp();

// Wait for the process to complete
let status = child.wait().context("Failed to wait for command")?;

// Measure elapsed time
let bench_end = InstrumentHooks::current_timestamp();
hooks.add_benchmark_timestamps(bench_start, bench_end);

// Exit immediately if any iteration fails
if !status.success() {
bail!("Command failed with exit code: {:?}", status.code());
}

// Calculate and store the elapsed time in nanoseconds
let elapsed_ns = (bench_end - bench_start) as u128;
times_per_round_ns.push(elapsed_ns);
}
// Build execution options from CLI args
let execution_options: walltime::ExecutionOptions = args.execution_args.try_into()?;

hooks.stop_benchmark().unwrap();
hooks.set_executed_benchmark(&bench_uri).unwrap();
let times_per_round_ns =
walltime::perform(bench_uri.clone(), args.command, &execution_options)?;

// Collect walltime results
let max_time_ns = times_per_round_ns.iter().copied().max();
let walltime_benchmark = WalltimeBenchmark::from_runtime_data(
bench_name.clone(),
bench_uri.clone(),
vec![1; NUM_ITERATIONS],
vec![1; times_per_round_ns.len()],
times_per_round_ns,
max_time_ns,
);
Expand Down
6 changes: 6 additions & 0 deletions crates/exec-harness/src/prelude.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pub use anyhow::Context;
pub use anyhow::Result;
pub use anyhow::bail;

#[allow(unused_imports)]
pub use log::{debug, error, info, trace, warn};
63 changes: 0 additions & 63 deletions crates/exec-harness/src/walltime.rs

This file was deleted.

Loading
Loading