184 lines
6.0 KiB
Rust
184 lines
6.0 KiB
Rust
//! Compare identical Git status calls with and without the journal in fresh worlds.
|
|
use sausage::{
|
|
exec::{Command, Exec, Options},
|
|
process::Runtime,
|
|
world::World,
|
|
};
|
|
use sausage_vfs::{Host, Mounts, Process};
|
|
use std::{path::PathBuf, sync::Arc, time::Instant};
|
|
// This timing benchmark has a 10% threshold and is flaky on a loaded machine.
|
|
#[tokio::test(flavor = "multi_thread")]
|
|
#[ignore = "Run this timing benchmark by hand on an idle machine"]
|
|
async fn status_cost() {
|
|
let target = PathBuf::from(std::env::var("CARGO_TARGET_DIR").unwrap());
|
|
if !target.join("wasm32-wasip2/release/git.wasm").is_file() {
|
|
let userland = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../userland");
|
|
crate::common::cwd_init();
|
|
assert!(
|
|
std::process::Command::new("cargo")
|
|
.args(["build", "--release", "-p", "git"])
|
|
.current_dir(&userland)
|
|
.status()
|
|
.unwrap()
|
|
.success()
|
|
);
|
|
}
|
|
let temp = tempfile::tempdir().unwrap();
|
|
let source = temp.path().join("source");
|
|
std::fs::create_dir_all(&source).unwrap();
|
|
let archive = std::process::Command::new("git")
|
|
.args([
|
|
"archive",
|
|
"HEAD",
|
|
"host",
|
|
"vfs",
|
|
"userland",
|
|
"Cargo.toml",
|
|
"Cargo.lock",
|
|
"flake.nix",
|
|
"flake.lock",
|
|
"README.md",
|
|
"AGENTS.md",
|
|
".gitignore",
|
|
])
|
|
.current_dir(PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(".."))
|
|
.output()
|
|
.unwrap();
|
|
assert!(archive.status.success());
|
|
let tar = temp.path().join("source.tar");
|
|
std::fs::write(&tar, archive.stdout).unwrap();
|
|
assert!(
|
|
std::process::Command::new("tar")
|
|
.arg("-xf")
|
|
.arg(&tar)
|
|
.arg("-C")
|
|
.arg(&source)
|
|
.status()
|
|
.unwrap()
|
|
.success()
|
|
);
|
|
for args in [
|
|
vec!["init"],
|
|
vec!["add", "."],
|
|
vec![
|
|
"-c",
|
|
"user.name=Test",
|
|
"-c",
|
|
"user.email=test@example.com",
|
|
"commit",
|
|
"--no-gpg-sign",
|
|
"-m",
|
|
"fixture",
|
|
],
|
|
] {
|
|
let output = std::process::Command::new("git")
|
|
.args(args)
|
|
.current_dir(&source)
|
|
.output()
|
|
.unwrap();
|
|
assert!(output.status.success());
|
|
}
|
|
let mut times = [Vec::new(), Vec::new()];
|
|
for round in 0..5 {
|
|
for enabled in if round % 2 == 0 {
|
|
[false, true]
|
|
} else {
|
|
[true, false]
|
|
} {
|
|
let instance = temp.path().join(format!("{round}-{enabled}"));
|
|
let mut world = World::open(&instance).unwrap();
|
|
let root = instance.join("world");
|
|
std::fs::create_dir_all(root.join("bin")).unwrap();
|
|
std::fs::create_dir_all(root.join("src")).unwrap();
|
|
std::fs::copy(
|
|
target.join("wasm32-wasip2/release/git.wasm"),
|
|
root.join("bin/git"),
|
|
)
|
|
.unwrap();
|
|
assert!(
|
|
std::process::Command::new("cp")
|
|
.arg("-R")
|
|
.arg(&source)
|
|
.arg(root.join("src/sausage"))
|
|
.status()
|
|
.unwrap()
|
|
.success()
|
|
);
|
|
if !enabled {
|
|
let mut mounts = Mounts::default();
|
|
mounts.mount(
|
|
"/",
|
|
Arc::new(Host::new(&root, Process::default()).unwrap()),
|
|
false,
|
|
);
|
|
world.root = Arc::new(mounts);
|
|
}
|
|
let journal = world.root.journal();
|
|
let runtime = Runtime::new(world).unwrap();
|
|
let mut options = Options {
|
|
cwd: "/src/sausage".into(),
|
|
..Default::default()
|
|
};
|
|
assert_eq!(
|
|
runtime
|
|
.exec(
|
|
Command::Argv(vec!["/bin/git".into(), "status".into(), "--short".into()]),
|
|
options.clone(),
|
|
&mut |_, _| {}
|
|
)
|
|
.await
|
|
.unwrap(),
|
|
0
|
|
);
|
|
// Warm the copied repository's index, not only component compilation.
|
|
// Then require another index refresh in the measured call.
|
|
assert!(
|
|
std::process::Command::new("touch")
|
|
.arg(root.join("src/sausage/README.md"))
|
|
.status()
|
|
.unwrap()
|
|
.success()
|
|
);
|
|
options.tool_call = Some("measured".into());
|
|
let start = Instant::now();
|
|
assert_eq!(
|
|
runtime
|
|
.exec(
|
|
Command::Argv(vec!["/bin/git".into(), "status".into(), "--short".into()]),
|
|
options,
|
|
&mut |_, bytes| assert!(
|
|
bytes.is_empty(),
|
|
"{}",
|
|
String::from_utf8_lossy(bytes)
|
|
)
|
|
)
|
|
.await
|
|
.unwrap(),
|
|
0
|
|
);
|
|
times[usize::from(enabled)].push(start.elapsed().as_secs_f64());
|
|
if let Some(journal) = journal {
|
|
assert!(
|
|
journal
|
|
.show("measured".into())
|
|
.await
|
|
.unwrap()
|
|
.iter()
|
|
.any(|snapshot| snapshot.path == "/src/sausage/.git/index")
|
|
);
|
|
}
|
|
}
|
|
}
|
|
for values in &mut times {
|
|
values.sort_by(f64::total_cmp);
|
|
}
|
|
println!(
|
|
"status without journal: {:.6}s; with journal: {:.6}s",
|
|
times[0][2], times[1][2]
|
|
);
|
|
assert!(
|
|
times[1][2] <= times[0][2] * 1.10,
|
|
"journal exceeds ten percent"
|
|
);
|
|
}
|