Skip to content
Draft
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: 8 additions & 3 deletions crates/exec-harness/src/analysis/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,20 @@ pub fn perform(commands: Vec<BenchmarkCommand>) -> Result<()> {
cmd.args(&benchmark_cmd.command[1..]);

hooks.start_benchmark().unwrap();
let status = cmd.status();
let result = cmd.spawn().and_then(|mut child| {
let pid = child.id();
child.wait().map(|status| (pid, status))
});
hooks.stop_benchmark().unwrap();
let status = status.context("Failed to execute command")?;
let (pid, status) = result.context("Failed to execute command")?;

if !status.success() {
bail!("Command exited with non-zero status: {status}");
}

hooks.set_executed_benchmark(&name_and_uri.uri).unwrap();
hooks
.set_executed_benchmark_for_pid(pid, &name_and_uri.uri)
.unwrap();
}

Ok(())
Expand Down
18 changes: 16 additions & 2 deletions crates/instrument-hooks-bindings/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,15 @@ mod linux_impl {

#[inline(always)]
pub fn set_executed_benchmark(&self, uri: &str) -> Result<(), u8> {
let pid = std::process::id() as i32;
self.set_executed_benchmark_for_pid(std::process::id(), uri)
}

/// Declares a benchmark that ran in the process `pid` rather than in this one.
#[inline(always)]
pub fn set_executed_benchmark_for_pid(&self, pid: u32, uri: &str) -> Result<(), u8> {
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())
ffi::instrument_hooks_set_executed_benchmark(self.0, pid as i32, c_uri.as_ptr())
};
if result == 0 { Ok(()) } else { Err(result) }
}
Expand Down Expand Up @@ -184,6 +189,10 @@ mod other_impl {
Ok(())
}

pub fn set_executed_benchmark_for_pid(&self, _pid: u32, _uri: &str) -> Result<(), u8> {
Ok(())
}

pub fn set_integration(&self, _name: &str, _version: &str) -> Result<(), u8> {
Ok(())
}
Expand Down Expand Up @@ -213,6 +222,11 @@ mod tests {
let hooks = InstrumentHooks::instance("test_integration", "1.0.0");
assert!(!hooks.is_instrumented() || hooks.start_benchmark().is_ok());
assert!(hooks.set_executed_benchmark("test_uri").is_ok());
assert!(
hooks
.set_executed_benchmark_for_pid(std::process::id() + 1, "test_uri")
.is_ok()
);
assert!(hooks.set_integration("test_integration", "1.0.0").is_ok());
let start = InstrumentHooks::current_timestamp();
let end = start + 1_000_000; // Simulate 1ms later
Expand Down
10 changes: 5 additions & 5 deletions src/binary_pins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub const VALGRIND_CODSPEED_VERSION: Version = Version::new(3, 26, 0);
/// the .deb is repackaged without a new upstream valgrind release. Appears in
/// the .deb package version (`3.26.0-0codspeed3`) and in `valgrind --version`
/// output (`valgrind-3.26.0.codspeed3`).
pub const VALGRIND_CODSPEED_ITERATION: u32 = 7;
pub const VALGRIND_CODSPEED_ITERATION: u32 = 8;
/// Suffix appended to `VALGRIND_CODSPEED_VERSION` to form the .deb package version.
static VALGRIND_DEB_REV: LazyLock<String> =
LazyLock::new(|| format!("0codspeed{VALGRIND_CODSPEED_ITERATION}"));
Expand Down Expand Up @@ -93,16 +93,16 @@ impl ValgrindTarget {
fn sha256(self) -> &'static str {
match (self.distro_version, self.arch) {
(DistroVersion::Ubuntu2204, Arch::Amd64) => {
"658a64049b6a1f5bec9c038b8036f9a61fee83011a909b649e32a82edab4ba99"
"9836998817cd6d12e86bf60a230634f9f11594a1d21fcbd580a47b693ec5b6d1"
}
(DistroVersion::Ubuntu2404, Arch::Amd64) => {
"ea1788e43cfd75b8af84dd496eb265307c6ab6d048cb7bc8ba4bc564dbbd5aba"
"edee86d0d61b46435ea3f4a73ffb222fcf8d605a9e3901638f280197c3c3d602"
}
(DistroVersion::Ubuntu2204, Arch::Arm64) => {
"6db07f15ce23e3cfda00bda85aac0ea3b8a2261c00d529ed856ceb7f3ba207f6"
"453e2455a3a924c2b2e93201336fb9b7904f1154bf9304bf910da884cee27052"
}
(DistroVersion::Ubuntu2404, Arch::Arm64) => {
"0bccdaf2da7202ff4fe15e8301641c3a0abd46879c03713150cb5f21d6c9baaf"
"1884667fe9da4f991476b97108d021341b0456ebc5185430a1748e57f4cccc52"
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions src/executor/valgrind/measure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ fn get_valgrind_args(tool: &SimulationTool, config: &ExecutorConfig) -> Vec<Stri
children_skip_patterns.join(",")
));

// Internal subcommands run through the runner's own executable, which may
// carry file capabilities that valgrind refuses to run by default. They
// do not need those capabilities.
if let Ok(self_exe) = crate::cli::self_exe() {
args.push(format!("--allow-file-caps={}", self_exe.display()));
}

if config.fair_sched {
args.push("--fair-sched=yes".to_string());
}
Expand Down
8 changes: 4 additions & 4 deletions src/executor/valgrind/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ mod tests {
};
assert_snapshot!(
get_codspeed_valgrind_binary(&system_info).unwrap().url(),
@"https://github.com/CodSpeedHQ/valgrind-codspeed/releases/download/3.26.0-0codspeed7/valgrind_3.26.0-0codspeed7_ubuntu-22.04_amd64.deb"
@"https://github.com/CodSpeedHQ/valgrind-codspeed/releases/download/3.26.0-0codspeed8/valgrind_3.26.0-0codspeed8_ubuntu-22.04_amd64.deb"
);
}

Expand All @@ -359,7 +359,7 @@ mod tests {
};
assert_snapshot!(
get_codspeed_valgrind_binary(&system_info).unwrap().url(),
@"https://github.com/CodSpeedHQ/valgrind-codspeed/releases/download/3.26.0-0codspeed7/valgrind_3.26.0-0codspeed7_ubuntu-24.04_amd64.deb"
@"https://github.com/CodSpeedHQ/valgrind-codspeed/releases/download/3.26.0-0codspeed8/valgrind_3.26.0-0codspeed8_ubuntu-24.04_amd64.deb"
);
}

Expand All @@ -374,7 +374,7 @@ mod tests {
};
assert_snapshot!(
get_codspeed_valgrind_binary(&system_info).unwrap().url(),
@"https://github.com/CodSpeedHQ/valgrind-codspeed/releases/download/3.26.0-0codspeed7/valgrind_3.26.0-0codspeed7_ubuntu-22.04_amd64.deb"
@"https://github.com/CodSpeedHQ/valgrind-codspeed/releases/download/3.26.0-0codspeed8/valgrind_3.26.0-0codspeed8_ubuntu-22.04_amd64.deb"
);
}

Expand All @@ -389,7 +389,7 @@ mod tests {
};
assert_snapshot!(
get_codspeed_valgrind_binary(&system_info).unwrap().url(),
@"https://github.com/CodSpeedHQ/valgrind-codspeed/releases/download/3.26.0-0codspeed7/valgrind_3.26.0-0codspeed7_ubuntu-22.04_arm64.deb"
@"https://github.com/CodSpeedHQ/valgrind-codspeed/releases/download/3.26.0-0codspeed8/valgrind_3.26.0-0codspeed8_ubuntu-22.04_arm64.deb"
);
}

Expand Down
2 changes: 1 addition & 1 deletion tests/docker/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ memory=()
walltime=()
while read -r name; do
case $name in
*Simulation*) simulation+=("$name") ;;
*Simulation* | simulation_*) simulation+=("$name") ;;
*Memory* | memory_*) memory+=("$name") ;;
*) walltime+=("$name") ;;
esac
Expand Down
45 changes: 45 additions & 0 deletions tests/executors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,51 @@ fn walltime_exec_harness() {
.success();
}

/// exec-harness measures the command from its own process, so its part
/// must declare the pid of the spawned process that ran the benchmark.
#[test]
fn simulation_exec_harness_declares_benchmark_pid() {
let profile_folder = tempfile::tempdir().unwrap();
let _guard = Mode::Simulation.acquire();
codspeed()
.args(["exec", "--mode", "simulation", "--skip-upload"])
.arg("--profile-folder")
.arg(profile_folder.path())
.args(["--", "sh", "-c", "ls > /dev/null"])
.assert()
.success();

let profiles: Vec<(String, String)> = std::fs::read_dir(profile_folder.path())
.unwrap()
.map(|entry| entry.unwrap().path())
.filter(|path| path.extension().is_some_and(|ext| ext == "out"))
.map(|path| {
let pid = path.file_stem().unwrap().to_string_lossy().into_owned();
(pid, std::fs::read_to_string(&path).unwrap())
})
.collect();

let declarations: Vec<(&str, &str)> = profiles
.iter()
.flat_map(|(pid, content)| {
content
.lines()
.filter_map(|line| line.strip_prefix("desc: Benchmark pid: "))
.map(move |benchmark_pid| (pid.as_str(), benchmark_pid))
})
.collect();
let [(harness_pid, benchmark_pid)] = declarations.as_slice() else {
panic!("expected exactly one benchmark pid declaration, got {declarations:?}");
};

assert_ne!(harness_pid, benchmark_pid);
assert!(
profiles.iter().any(|(pid, _)| pid == benchmark_pid),
"benchmark pid {benchmark_pid} has no profile among {:?}",
profiles.iter().map(|(pid, _)| pid).collect::<Vec<_>>()
);
}

/// Prepends `prefix` to `var` and checks the benchmark still sees it.
fn memory_forwards_path_like(var: &str, prefix: &str) {
let value = match std::env::var(var).unwrap_or_default() {
Expand Down
Loading