Skip to content

Commit 8168b3f

Browse files
committed
feat: add pre- and post-benchmark scripts
1 parent 25dd365 commit 8168b3f

1 file changed

Lines changed: 101 additions & 2 deletions

File tree

  • src/run/runner/wall_time/perf

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

Lines changed: 101 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use metadata::PerfMetadata;
1414
use perf_map::ProcessSymbols;
1515
use shared::Command as FifoCommand;
1616
use std::collections::HashSet;
17-
use std::path::PathBuf;
17+
use std::path::{Path, PathBuf};
1818
use std::process::Command;
1919
use std::time::Duration;
2020
use std::{cell::OnceCell, collections::HashMap, process::ExitStatus};
@@ -33,6 +33,55 @@ pub mod unwind_data;
3333

3434
const PERF_DATA_PREFIX: &str = "perf.data.";
3535

36+
struct EnvGuard {
37+
post_bench_script: PathBuf,
38+
}
39+
40+
impl EnvGuard {
41+
fn execute_script_from_path<P: AsRef<Path>>(path: P) -> anyhow::Result<()> {
42+
let path = path.as_ref();
43+
if !path.exists() || !path.is_file() {
44+
warn!("Script not found or not a file: {}", path.display());
45+
return Ok(());
46+
}
47+
48+
let output = Command::new("bash").args([&path]).output()?;
49+
if !output.status.success() {
50+
info!("stdout: {}", String::from_utf8_lossy(&output.stdout));
51+
error!("stderr: {}", String::from_utf8_lossy(&output.stderr));
52+
bail!("Failed to execute script: {}", path.display());
53+
}
54+
55+
Ok(())
56+
}
57+
58+
pub fn setup_with_scripts<P: AsRef<Path>>(pre_bench_script: P, post_bench_script: P) -> Self {
59+
if let Err(e) = Self::execute_script_from_path(pre_bench_script.as_ref()) {
60+
warn!("Failed to execute pre-bench script: {}", e);
61+
println!("asdf: {e}");
62+
}
63+
64+
Self {
65+
post_bench_script: post_bench_script.as_ref().to_path_buf(),
66+
}
67+
}
68+
69+
pub fn setup() -> Self {
70+
Self::setup_with_scripts(
71+
"/usr/local/bin/codspeed-pre-bench",
72+
"/usr/local/bin/codspeed-post-bench",
73+
)
74+
}
75+
}
76+
77+
impl Drop for EnvGuard {
78+
fn drop(&mut self) {
79+
if let Err(e) = Self::execute_script_from_path(&self.post_bench_script) {
80+
warn!("Failed to execute post-bench script: {}", e);
81+
}
82+
}
83+
}
84+
3685
pub struct PerfRunner {
3786
perf_dir: TempDir,
3887
benchmark_data: OnceCell<BenchmarkData>,
@@ -139,7 +188,11 @@ impl PerfRunner {
139188

140189
Ok(())
141190
};
142-
run_command_with_log_pipe_and_callback(cmd, on_process_started).await
191+
192+
{
193+
let _guard = EnvGuard::setup();
194+
run_command_with_log_pipe_and_callback(cmd, on_process_started).await
195+
}
143196
}
144197

145198
pub async fn save_files_to(&self, profile_folder: &PathBuf) -> anyhow::Result<()> {
@@ -402,3 +455,49 @@ impl BenchmarkData {
402455
self.bench_order_by_pid.values().map(|v| v.len()).sum()
403456
}
404457
}
458+
#[cfg(test)]
459+
mod tests {
460+
use tempfile::NamedTempFile;
461+
462+
use super::*;
463+
use std::{
464+
io::{Read, Write},
465+
os::unix::fs::PermissionsExt,
466+
};
467+
468+
#[test]
469+
fn test_env_guard_no_crash() {
470+
fn create_run_script(content: &str) -> anyhow::Result<NamedTempFile> {
471+
let rwx = std::fs::Permissions::from_mode(0o777);
472+
let mut script_file = tempfile::Builder::new()
473+
.suffix(".sh")
474+
.permissions(rwx)
475+
.keep(true)
476+
.tempfile()?;
477+
script_file.write_all(content.as_bytes())?;
478+
479+
Ok(script_file)
480+
}
481+
482+
let mut tmp_dst = tempfile::NamedTempFile::new().unwrap();
483+
484+
let pre_script = create_run_script(&format!(
485+
"#!/usr/bin/env bash\necho \"pre\" >> {}",
486+
tmp_dst.path().display()
487+
))
488+
.unwrap();
489+
let post_script = create_run_script(&format!(
490+
"#!/usr/bin/env bash\necho \"post\" >> {}",
491+
tmp_dst.path().display()
492+
))
493+
.unwrap();
494+
495+
{
496+
let _guard = EnvGuard::setup_with_scripts(pre_script.path(), post_script.path());
497+
}
498+
499+
let mut result = String::new();
500+
tmp_dst.read_to_string(&mut result).unwrap();
501+
assert_eq!(result, "pre\npost\n");
502+
}
503+
}

0 commit comments

Comments
 (0)