Skip to content

Commit 03bac06

Browse files
committed
add simple benchmark script for entrace_example
1 parent eb439c2 commit 03bac06

File tree

5 files changed

+213
-3
lines changed

5 files changed

+213
-3
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@
66
**/**.et
77
.direnv
88
result
9+
.bench

Cargo.lock

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

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[workspace]
22
resolver = "2"
3-
members = ["example", "gui", "entrace_core"]
3+
members = ["example", "gui", "entrace_core", "bench"]
44

55
[profile.profiling]
66
inherits = 'release'

bench/Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[package]
2+
name = "bench"
3+
version = "0.1.0"
4+
edition = "2024"
5+
6+
[dependencies]
7+
anyhow = "1.0.100"
8+
command-error = "0.8.0"

bench/src/main.rs

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
use anyhow::bail;
2+
use command_error::CommandExt;
3+
use std::{error::Error, io::Write, path::PathBuf, process::Command, time::Duration};
4+
5+
#[derive(Debug)]
6+
enum SourceDesc {
7+
GitRevision(String),
8+
DirtyRev,
9+
}
10+
11+
impl SourceDesc {
12+
pub fn executable_name(&self) -> &str {
13+
match self {
14+
SourceDesc::GitRevision(x) => x,
15+
SourceDesc::DirtyRev => "dirty",
16+
}
17+
}
18+
}
19+
20+
fn canonicalize_commit(s: &str) -> anyhow::Result<String> {
21+
let can = Command::new("git").arg("rev-parse").arg(s).output_checked()?;
22+
let str = str::from_utf8(&can.stdout)?.trim().to_string();
23+
Ok(str)
24+
}
25+
26+
fn parse_source_desc(s: &str) -> anyhow::Result<SourceDesc> {
27+
if let Some(end) = s.strip_prefix("Git(") {
28+
if let Some(rev) = end.strip_suffix(")") {
29+
let canonicalized = canonicalize_commit(rev)?;
30+
return Ok(SourceDesc::GitRevision(canonicalized));
31+
} else {
32+
bail!("Bad SourceDesc::Git {s}");
33+
}
34+
}
35+
if s == "." || s == "./" {
36+
return Ok(SourceDesc::DirtyRev);
37+
};
38+
bail!("Cannot parse source desc {s}")
39+
}
40+
41+
fn ensure_benchmark_dir() -> Result<(PathBuf, PathBuf), Box<dyn Error>> {
42+
let rpo = Command::new("git").arg("rev-parse").arg("--show-toplevel").output()?;
43+
let toplevel = PathBuf::from(str::from_utf8(&rpo.stdout)?.trim());
44+
let bench_p = toplevel.join(".bench");
45+
std::fs::create_dir(&bench_p).ok();
46+
Ok((toplevel, bench_p))
47+
}
48+
49+
fn get_original_checkout() -> Result<String, Box<dyn Error>> {
50+
let head = Command::new("git").arg("rev-parse").arg("--abbrev-ref").arg("HEAD").output()?;
51+
let mut o = String::from_utf8(head.stdout)?;
52+
o.pop();
53+
Ok(o)
54+
}
55+
fn join(mut it: impl Iterator<Item: AsRef<str>>, sep: char) -> String {
56+
let mut x = it.by_ref().fold(String::new(), |mut acc, x| {
57+
acc.push_str(x.as_ref());
58+
acc.push(sep);
59+
acc
60+
});
61+
x.pop();
62+
x
63+
}
64+
fn main_inner() -> Result<(), Box<dyn Error>> {
65+
let mut args = std::env::args().skip(1);
66+
let (toplevel, benchdir) = ensure_benchmark_dir()?;
67+
info!("toplevel directory is {toplevel:?}");
68+
let sources: anyhow::Result<Vec<SourceDesc>> =
69+
args.by_ref().take_while(|x| x != "--").map(|x| parse_source_desc(x.trim())).collect();
70+
let bench_args = args;
71+
let sources = sources?;
72+
if sources.is_empty() {
73+
warning!("No sources given");
74+
warning!(
75+
"Help: Call this script like: bench 'Git(HEAD~1)' 'Git(HEAD)' -- --log-mode disk-et --work spammer"
76+
);
77+
return Ok(());
78+
}
79+
let paths: Vec<PathBuf> = sources.iter().map(|x| benchdir.join(x.executable_name())).collect();
80+
for (source, path) in sources.iter().zip(&paths) {
81+
if std::fs::exists(path).unwrap_or(false)
82+
&& let SourceDesc::GitRevision(_) = source
83+
{
84+
debug!("Already have {path:?}.");
85+
continue;
86+
}
87+
88+
if let SourceDesc::GitRevision(x) = source {
89+
debug!("Checking out and compiling {x}");
90+
Command::new("git").arg("checkout").arg(x).output_checked()?;
91+
} else {
92+
debug!("Compiling dirty revision");
93+
}
94+
Command::new("cargo")
95+
.args(["build", "-p", "entrace_example", "--release"])
96+
.output_checked()?;
97+
std::fs::copy(toplevel.join("target/release/entrace_example"), path)?;
98+
}
99+
info!("Built everything, waiting 0.5s to avoid interference");
100+
std::thread::sleep(Duration::from_millis(500));
101+
let mut cmd = Command::new("poop");
102+
let args_joined = join(bench_args, ' ');
103+
for path in paths {
104+
cmd.arg(format!("{} {args_joined}", path.to_string_lossy()));
105+
}
106+
cmd.spawn()?.wait()?;
107+
108+
Ok(())
109+
}
110+
fn main() -> Result<(), Box<dyn Error>> {
111+
let initial_commit = get_original_checkout()?;
112+
let inner_res = main_inner();
113+
info!("Checking out original revision ({initial_commit})");
114+
Command::new("git").arg("checkout").arg(initial_commit).output_checked()?;
115+
inner_res
116+
}
117+
118+
pub const GREY: &str = "\x1b[90m";
119+
pub const GREEN: &str = "\x1b[32m";
120+
pub const BLUE: &str = "\x1b[34m";
121+
pub const YELLOW: &str = "\x1b[33m";
122+
pub const RED: &str = "\x1b[31m";
123+
pub const RESET: &str = "\x1b[0m";
124+
pub const BOLD: &str = "\x1b[1m";
125+
pub const RESET_BOLD: &str = "\x1b[22m";
126+
#[macro_export]
127+
macro_rules! info {
128+
($($a:expr),*) => {
129+
let mut stderr = std::io::stderr().lock();
130+
write!(stderr, "{BLUE}{BOLD}[I]:{RESET} ").ok();
131+
writeln!(stderr, $($a),*).ok();
132+
};
133+
}
134+
135+
#[macro_export]
136+
macro_rules! debug {
137+
($($a:expr),*) => {
138+
let mut stderr = std::io::stderr().lock();
139+
use std::io::Write;
140+
write!(stderr, "{GREEN}{BOLD}[D]:{RESET} ").ok();
141+
writeln!(stderr, $($a),*).ok();
142+
};
143+
}
144+
#[macro_export]
145+
macro_rules! warning {
146+
($($a:expr),*) => {
147+
let mut stderr = std::io::stderr().lock();
148+
write!(stderr, "{YELLOW}{BOLD}[W]:{RESET} ").ok();
149+
writeln!(stderr, $($a),*).ok();
150+
};
151+
}

0 commit comments

Comments
 (0)