Skip to content

Commit 17c9f5e

Browse files
committed
feat: add pre- and post-benchmark scripts
1 parent 79b3ae1 commit 17c9f5e

1 file changed

Lines changed: 130 additions & 1 deletion

File tree

  • src/run/runner/wall_time/perf

src/run/runner/wall_time/perf/mod.rs

Lines changed: 130 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,52 @@ pub mod unwind_data;
3131

3232
const PERF_DATA_PREFIX: &str = "perf.data.";
3333

34+
struct EnvGuard;
35+
36+
impl EnvGuard {
37+
fn execute_script_from_env(script_env_var: &str) -> anyhow::Result<()> {
38+
let Ok(script_path) = std::env::var(script_env_var) else {
39+
debug!("Couldn't find {script_env_var}, skipping script execution");
40+
return Ok(());
41+
};
42+
43+
if script_path.is_empty() {
44+
return Ok(());
45+
}
46+
47+
let path = std::path::Path::new(&script_path);
48+
if !path.exists() || !path.is_file() {
49+
warn!("Script not found or not a file: {}", script_path);
50+
return Ok(());
51+
}
52+
53+
let output = Command::new("bash").args([&script_path]).output()?;
54+
if !output.status.success() {
55+
info!("stdout: {}", String::from_utf8_lossy(&output.stdout));
56+
error!("stderr: {}", String::from_utf8_lossy(&output.stderr));
57+
bail!("Failed to execute script: {}", script_path);
58+
}
59+
60+
Ok(())
61+
}
62+
63+
pub fn setup() -> Self {
64+
if let Err(e) = Self::execute_script_from_env("CODSPEED_PRE_STARTUP_SCRIPT") {
65+
warn!("Failed to execute pre-startup script: {}", e);
66+
println!("asdf: {e}");
67+
}
68+
Self
69+
}
70+
}
71+
72+
impl Drop for EnvGuard {
73+
fn drop(&mut self) {
74+
if let Err(e) = Self::execute_script_from_env("CODSPEED_POST_CLEANUP_SCRIPT") {
75+
warn!("Failed to execute post-cleanup script: {}", e);
76+
}
77+
}
78+
}
79+
3480
pub struct PerfRunner {
3581
perf_dir: TempDir,
3682
benchmark_data: OnceCell<BenchmarkData>,
@@ -126,7 +172,11 @@ impl PerfRunner {
126172

127173
Ok(())
128174
};
129-
run_command_with_log_pipe_and_callback(cmd, on_process_started).await
175+
176+
{
177+
let _guard = EnvGuard::setup();
178+
run_command_with_log_pipe_and_callback(cmd, on_process_started).await
179+
}
130180
}
131181

132182
pub async fn save_files_to(&self, profile_folder: &PathBuf) -> anyhow::Result<()> {
@@ -389,3 +439,82 @@ impl BenchmarkData {
389439
self.bench_order_by_pid.values().map(|v| v.len()).sum()
390440
}
391441
}
442+
#[cfg(test)]
443+
mod tests {
444+
use tempfile::NamedTempFile;
445+
446+
use super::*;
447+
use std::{
448+
io::{Read, Write},
449+
os::unix::fs::PermissionsExt,
450+
};
451+
452+
fn with_env<F>(vars: &[(&str, &str)], mut f: F)
453+
where
454+
F: FnMut(),
455+
{
456+
let original_vars: Vec<(&str, std::result::Result<String, std::env::VarError>)> =
457+
vars.iter().map(|(k, _)| (*k, std::env::var(*k))).collect();
458+
459+
for (k, v) in vars {
460+
std::env::set_var(k, v);
461+
}
462+
463+
f();
464+
465+
for (k, v) in original_vars {
466+
if let Ok(val) = v {
467+
std::env::set_var(k, val);
468+
} else {
469+
std::env::remove_var(k);
470+
}
471+
}
472+
}
473+
474+
#[test]
475+
fn test_env_guard_no_crash() {
476+
fn create_run_script(content: &str) -> anyhow::Result<NamedTempFile> {
477+
let rwx = std::fs::Permissions::from_mode(0o777);
478+
let mut script_file = tempfile::Builder::new()
479+
.suffix(".sh")
480+
.permissions(rwx)
481+
.keep(true)
482+
.tempfile()?;
483+
script_file.write_all(content.as_bytes())?;
484+
485+
Ok(script_file)
486+
}
487+
488+
let mut tmp_dst = tempfile::NamedTempFile::new().unwrap();
489+
490+
let pre_script = create_run_script(&format!(
491+
"#!/usr/bin/env bash\necho \"pre\" >> {}",
492+
tmp_dst.path().display()
493+
))
494+
.unwrap();
495+
let post_script = create_run_script(&format!(
496+
"#!/usr/bin/env bash\necho \"post\" >> {}",
497+
tmp_dst.path().display()
498+
))
499+
.unwrap();
500+
501+
let env_vars = [
502+
(
503+
"CODSPEED_PRE_STARTUP_SCRIPT",
504+
&*pre_script.path().to_string_lossy(),
505+
),
506+
(
507+
"CODSPEED_POST_CLEANUP_SCRIPT",
508+
&post_script.path().to_string_lossy(),
509+
),
510+
];
511+
512+
with_env(&env_vars, || {
513+
let _guard = EnvGuard::setup();
514+
});
515+
516+
let mut result = String::new();
517+
tmp_dst.read_to_string(&mut result).unwrap();
518+
assert_eq!(result, "pre\npost\n");
519+
}
520+
}

0 commit comments

Comments
 (0)