Skip to content

Commit 73c2d7b

Browse files
committed
fix: execute pre- and post-bench scripts for non-perf walltime runner
1 parent bfe766f commit 73c2d7b

2 files changed

Lines changed: 111 additions & 110 deletions

File tree

src/run/runner/wall_time/executor.rs

Lines changed: 109 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,58 @@ use crate::run::{check_system::SystemInfo, config::Config};
1111
use async_trait::async_trait;
1212
use std::fs::canonicalize;
1313
use std::io::Write;
14+
use std::path::{Path, PathBuf};
1415
use std::process::Command;
1516
use tempfile::NamedTempFile;
1617

18+
struct HookScriptsGuard {
19+
post_bench_script: PathBuf,
20+
}
21+
22+
impl HookScriptsGuard {
23+
fn execute_script_from_path<P: AsRef<Path>>(path: P) -> anyhow::Result<()> {
24+
let path = path.as_ref();
25+
if !path.exists() || !path.is_file() {
26+
debug!("Script not found or not a file: {}", path.display());
27+
return Ok(());
28+
}
29+
30+
let output = Command::new("bash").args([&path]).output()?;
31+
if !output.status.success() {
32+
debug!("stdout: {}", String::from_utf8_lossy(&output.stdout));
33+
debug!("stderr: {}", String::from_utf8_lossy(&output.stderr));
34+
bail!("Failed to execute script: {}", path.display());
35+
}
36+
37+
Ok(())
38+
}
39+
40+
pub fn setup_with_scripts<P: AsRef<Path>>(pre_bench_script: P, post_bench_script: P) -> Self {
41+
if let Err(e) = Self::execute_script_from_path(pre_bench_script.as_ref()) {
42+
debug!("Failed to execute pre-bench script: {e}");
43+
}
44+
45+
Self {
46+
post_bench_script: post_bench_script.as_ref().to_path_buf(),
47+
}
48+
}
49+
50+
pub fn setup() -> Self {
51+
Self::setup_with_scripts(
52+
"/usr/local/bin/codspeed-pre-bench",
53+
"/usr/local/bin/codspeed-post-bench",
54+
)
55+
}
56+
}
57+
58+
impl Drop for HookScriptsGuard {
59+
fn drop(&mut self) {
60+
if let Err(e) = Self::execute_script_from_path(&self.post_bench_script) {
61+
debug!("Failed to execute post-bench script: {e}");
62+
}
63+
}
64+
}
65+
1766
pub struct WallTimeExecutor {
1867
perf: Option<PerfRunner>,
1968
}
@@ -86,17 +135,20 @@ impl Executor for WallTimeExecutor {
86135
cmd.current_dir(abs_cwd);
87136
}
88137

89-
let (_env_file, bench_cmd) = Self::walltime_bench_cmd(config, run_data)?;
138+
let status = {
139+
let _guard = HookScriptsGuard::setup();
90140

91-
let status = if let Some(perf) = &self.perf
92-
&& config.enable_perf
93-
{
94-
perf.run(cmd, &bench_cmd, config).await
95-
} else {
96-
cmd.args(["sh", "-c", &bench_cmd]);
97-
debug!("cmd: {cmd:?}");
141+
let (_env_file, bench_cmd) = Self::walltime_bench_cmd(config, run_data)?;
142+
if let Some(perf) = &self.perf
143+
&& config.enable_perf
144+
{
145+
perf.run(cmd, &bench_cmd, config).await
146+
} else {
147+
cmd.args(["sh", "-c", &bench_cmd]);
148+
debug!("cmd: {cmd:?}");
98149

99-
run_command_with_log_pipe(cmd).await
150+
run_command_with_log_pipe(cmd).await
151+
}
100152
};
101153

102154
let status =
@@ -127,3 +179,51 @@ impl Executor for WallTimeExecutor {
127179
Ok(())
128180
}
129181
}
182+
183+
#[cfg(test)]
184+
mod tests {
185+
use tempfile::NamedTempFile;
186+
187+
use super::*;
188+
use std::{
189+
io::{Read, Write},
190+
os::unix::fs::PermissionsExt,
191+
};
192+
193+
#[test]
194+
fn test_env_guard_no_crash() {
195+
fn create_run_script(content: &str) -> anyhow::Result<NamedTempFile> {
196+
let rwx = std::fs::Permissions::from_mode(0o777);
197+
let mut script_file = tempfile::Builder::new()
198+
.suffix(".sh")
199+
.permissions(rwx)
200+
.keep(true)
201+
.tempfile()?;
202+
script_file.write_all(content.as_bytes())?;
203+
204+
Ok(script_file)
205+
}
206+
207+
let mut tmp_dst = tempfile::NamedTempFile::new().unwrap();
208+
209+
let pre_script = create_run_script(&format!(
210+
"#!/usr/bin/env bash\necho \"pre\" >> {}",
211+
tmp_dst.path().display()
212+
))
213+
.unwrap();
214+
let post_script = create_run_script(&format!(
215+
"#!/usr/bin/env bash\necho \"post\" >> {}",
216+
tmp_dst.path().display()
217+
))
218+
.unwrap();
219+
220+
{
221+
let _guard =
222+
HookScriptsGuard::setup_with_scripts(pre_script.path(), post_script.path());
223+
}
224+
225+
let mut result = String::new();
226+
tmp_dst.read_to_string(&mut result).unwrap();
227+
assert_eq!(result, "pre\npost\n");
228+
}
229+
}

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

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

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

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

183134
Ok(())
184135
};
185-
186-
{
187-
let _guard = EnvGuard::setup();
188-
run_command_with_log_pipe_and_callback(cmd, on_process_started).await
189-
}
136+
run_command_with_log_pipe_and_callback(cmd, on_process_started).await
190137
}
191138

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

0 commit comments

Comments
 (0)