use std::time::Instant;
use supermachine::Image;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let home = std::env::var("HOME")?;
let name = std::env::var("ONE_SHOT_NAME").unwrap_or_else(|_| "_one_shot_timing".to_string());
let snap_dir = format!("{home}/.local/supermachine-snapshots/{name}");
if std::env::var("ONE_SHOT_CLEAN").ok().as_deref() == Some("1") {
let _ = std::fs::remove_dir_all(&snap_dir);
}
let total_t0 = Instant::now();
let mut b = Image::builder("rust:1-slim").with_name(&name);
if std::env::var("ONE_SHOT_NEVER_PULL").ok().as_deref() == Some("1") {
b = b.with_pull_policy(supermachine::PullPolicy::Never);
}
let image = b.build()?;
let bake_ms = total_t0.elapsed().as_millis();
eprintln!("[oneshot] Image::builder().build(): {} ms", bake_ms);
let meta_path = format!("{snap_dir}/metadata.json");
if let Ok(s) = std::fs::read_to_string(&meta_path) {
if let Ok(v) = serde_json::from_str::<serde_json::Value>(&s) {
if let Some(t) = v.get("timings") {
eprintln!("[oneshot] phases:");
let print_key = |k: &str| {
if let Some(val) = t.get(k) {
eprintln!(" {}: {}", k, val);
}
};
for k in [
"pull_inspect_ms",
"rootfs_prepare_ms",
"rootfs_customize_ms",
"squashfs_ms",
"initramfs_ms",
"vmm_bake_ms",
"metadata_prepare_ms",
"guest_boot_to_listener_ms",
"snapshot_capture_us",
"snapshot_save_us",
"total_ms",
] {
print_key(k);
}
}
}
}
let pool = image.pool().min(0).max(1).build()?;
let acquire_t0 = Instant::now();
let vm = pool.acquire()?;
let acquire_ms = acquire_t0.elapsed().as_millis();
eprintln!("[oneshot] pool.build() done; acquire took {} ms", acquire_ms);
let exec_t0 = Instant::now();
let _ = vm
.exec_builder()
.argv(["true"])
.timeout(std::time::Duration::from_secs(10))
.output()?;
let exec_ms = exec_t0.elapsed().as_millis();
eprintln!("[oneshot] exec /bin/true: {} ms", exec_ms);
eprintln!(
"[oneshot] TOTAL (Image::build + acquire + exec): {} ms",
total_t0.elapsed().as_millis()
);
Ok(())
}