Skip to content

Commit 38e6c97

Browse files
feat(exec-harness): implement the walltime benchmarking algorithm
1 parent eb3db98 commit 38e6c97

File tree

14 files changed

+1215
-107
lines changed

14 files changed

+1215
-107
lines changed

Cargo.lock

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ async-compression = { version = "0.4.5", features = ["tokio", "gzip"] }
4040
simplelog = { version = "0.12.1", default-features = false, features = [
4141
"termcolor",
4242
] }
43-
tempfile = "3.10.0"
43+
tempfile = { workspace = true }
4444
git2 = "0.20.2"
4545
nestify = "0.3.3"
4646
gql_client = { git = "https://github.com/CodSpeedHQ/gql-client-rs" }
@@ -59,6 +59,7 @@ nix = { version = "0.29.0", features = ["fs", "time", "user"] }
5959
futures = "0.3.31"
6060
runner-shared = { path = "crates/runner-shared" }
6161
memtrack = { path = "crates/memtrack", default-features = false }
62+
exec-harness = { path = "crates/exec-harness" }
6263
ipc-channel = "0.18"
6364
shellexpand = { version = "3.1.1", features = ["tilde"] }
6465
addr2line = "0.25"
@@ -85,14 +86,15 @@ members = ["crates/runner-shared", "crates/memtrack", "crates/exec-harness"]
8586

8687
[workspace.dependencies]
8788
anyhow = "1.0"
88-
clap = { version = "4.5", features = ["derive"] }
89+
clap = { version = "4.5", features = ["derive", "env"] }
8990
libc = "0.2"
9091
log = "0.4.28"
9192
serde_json = "1.0"
9293
serde = { version = "1.0.228", features = ["derive"] }
9394
ipc-channel = "0.18"
9495
itertools = "0.14.0"
9596
env_logger = "0.11.8"
97+
tempfile = "3.10.0"
9698

9799
[workspace.metadata.release]
98100
sign-tag = true

crates/exec-harness/Cargo.toml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,27 @@ edition = "2024"
55
repository = "https://github.com/CodSpeedHQ/runner"
66
publish = false
77

8+
[lib]
9+
name = "exec_harness"
10+
path = "src/lib.rs"
11+
12+
[[bin]]
13+
name = "exec-harness"
14+
path = "src/main.rs"
15+
816
[dependencies]
917
anyhow = { workspace = true }
1018
codspeed = "4.1.0"
19+
log = { workspace = true }
20+
env_logger = { workspace = true }
1121
clap = { workspace = true }
1222
serde_json = { workspace = true }
1323
serde = { workspace = true }
24+
humantime = "2.1"
25+
runner-shared = { path = "../runner-shared" }
26+
27+
[dev-dependencies]
28+
tempfile = { workspace = true }
1429

1530
[package.metadata.dist]
1631
targets = ["aarch64-unknown-linux-musl", "x86_64-unknown-linux-musl"]

crates/exec-harness/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
//! CodSpeed exec-harness library
2+
//!
3+
//! This library provides the core functionality for wrapping commands
4+
//! with CodSpeed performance instrumentation.
5+
6+
mod prelude;
7+
pub mod walltime;

crates/exec-harness/src/main.rs

Lines changed: 16 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1+
use crate::prelude::*;
12
use crate::walltime::WalltimeResults;
2-
use anyhow::Context;
3-
use anyhow::Result;
4-
use anyhow::bail;
53
use clap::Parser;
64
use codspeed::instrument_hooks::InstrumentHooks;
7-
use codspeed::walltime_results::WalltimeBenchmark;
5+
use runner_shared::walltime_results::WalltimeBenchmark;
86
use std::path::PathBuf;
9-
use std::process;
107

8+
mod prelude;
119
mod walltime;
1210

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

22+
#[command(flatten)]
23+
execution_args: walltime::WalltimeExecutionArgs,
24+
2425
/// The command and arguments to execute
2526
command: Vec<String>,
2627
}
2728

2829
fn main() -> Result<()> {
30+
env_logger::builder()
31+
.parse_env(env_logger::Env::new().filter_or("CODSPEED_LOG", "info"))
32+
.format_timestamp(None)
33+
.init();
34+
2935
let args = Args::parse();
3036

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

52-
const NUM_ITERATIONS: usize = 1;
53-
let mut times_per_round_ns = Vec::with_capacity(NUM_ITERATIONS);
54-
55-
hooks.start_benchmark().unwrap();
56-
for _ in 0..NUM_ITERATIONS {
57-
// Spawn the command
58-
let mut child = process::Command::new(&args.command[0])
59-
.args(&args.command[1..])
60-
.spawn()
61-
.context("Failed to spawn command")?;
62-
63-
// Start monotonic timer for this iteration
64-
let bench_start = InstrumentHooks::current_timestamp();
65-
66-
// Wait for the process to complete
67-
let status = child.wait().context("Failed to wait for command")?;
68-
69-
// Measure elapsed time
70-
let bench_end = InstrumentHooks::current_timestamp();
71-
hooks.add_benchmark_timestamps(bench_start, bench_end);
72-
73-
// Exit immediately if any iteration fails
74-
if !status.success() {
75-
bail!("Command failed with exit code: {:?}", status.code());
76-
}
77-
78-
// Calculate and store the elapsed time in nanoseconds
79-
let elapsed_ns = (bench_end - bench_start) as u128;
80-
times_per_round_ns.push(elapsed_ns);
81-
}
58+
// Build execution options from CLI args
59+
let execution_options: walltime::ExecutionOptions = args.execution_args.try_into()?;
8260

83-
hooks.stop_benchmark().unwrap();
84-
hooks.set_executed_benchmark(&bench_uri).unwrap();
61+
let times_per_round_ns =
62+
walltime::perform(bench_uri.clone(), args.command, &execution_options)?;
8563

8664
// Collect walltime results
8765
let max_time_ns = times_per_round_ns.iter().copied().max();
8866
let walltime_benchmark = WalltimeBenchmark::from_runtime_data(
8967
bench_name.clone(),
9068
bench_uri.clone(),
91-
vec![1; NUM_ITERATIONS],
69+
vec![1; times_per_round_ns.len()],
9270
times_per_round_ns,
9371
max_time_ns,
9472
);

crates/exec-harness/src/prelude.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pub use anyhow::Context;
2+
pub use anyhow::Result;
3+
pub use anyhow::bail;
4+
5+
#[allow(unused_imports)]
6+
pub use log::{debug, error, info, trace, warn};

crates/exec-harness/src/walltime.rs

Lines changed: 0 additions & 63 deletions
This file was deleted.

0 commit comments

Comments
 (0)