import argparse
import json
import os
import subprocess
import sys
from pathlib import Path
from benchmark_common import (
BENCHMARK_RESULTS_DIR,
CARGO_BIN_DIR,
MITTS_BIN,
SCCACHE_BIN,
)
from benchmark_scenarios import (
run_s1_cold_build,
run_s2_fast_noop,
run_s3_git_history_replay,
run_s4_branch_hopping,
run_s5a_cold_swarm,
run_s5b_warm_swarm,
)
BENCH_ROOT = Path(os.environ.get("BENCH_ROOT", Path.home() / "mitts-benchmarks"))
PROJECTS_DIR = Path(os.environ.get("PROJECTS_DIR", BENCH_ROOT / "projects"))
SHARED_TARGET_ROOT = Path(os.environ.get("SHARED_TARGET_ROOT", BENCH_ROOT / "shared_cargo_target"))
def parse_args():
parser = argparse.ArgumentParser(description="Mitts Defensible Benchmark Runner")
parser.add_argument("--project", default="ripgrep", help="Target project to benchmark (default: ripgrep)")
parser.add_argument("--commits", type=int, default=10, help="Number of commits for Git history replay (default: 10)")
parser.add_argument("--output", default=None, help="Output JSON path")
return parser.parse_args()
def setup_environments(project_name):
shared_cas = BENCH_ROOT / f"cas_bench_{project_name}"
sccache_dir = BENCH_ROOT / f"sccache_bench_{project_name}"
shared_target_dir = SHARED_TARGET_ROOT / project_name
shared_target_dir.mkdir(parents=True, exist_ok=True)
env_cargo_bare = os.environ.copy()
env_cargo_bare["RUSTC_WRAPPER"] = ""
env_cargo_bare_no_incr = os.environ.copy()
env_cargo_bare_no_incr["RUSTC_WRAPPER"] = ""
env_cargo_bare_no_incr["CARGO_INCREMENTAL"] = "0"
env_cargo_shared = os.environ.copy()
env_cargo_shared["CARGO_TARGET_DIR"] = str(shared_target_dir)
env_cargo_shared["RUSTC_WRAPPER"] = ""
env_sccache = os.environ.copy()
env_sccache["RUSTC_WRAPPER"] = str(SCCACHE_BIN)
env_sccache["SCCACHE_DIR"] = str(sccache_dir)
env_sccache["CARGO_INCREMENTAL"] = "0"
env_mitts = os.environ.copy()
env_mitts["MITTS_CACHE_DIR"] = str(shared_cas)
return {
"mitts": env_mitts,
"cargo_bare": env_cargo_bare,
"cargo_bare_no_incr": env_cargo_bare_no_incr,
"cargo_shared": env_cargo_shared,
"sccache": env_sccache,
"mitts_cas": shared_cas,
"sccache_dir": sccache_dir,
"shared_target": shared_target_dir,
}
def main():
args = parse_args()
project_name = args.project
repo_dir = PROJECTS_DIR / project_name
worktree_base_dir = BENCH_ROOT / f"worktrees_{project_name}"
if not repo_dir.exists():
print(f"Error: Project directory {repo_dir} does not exist.")
sys.exit(1)
print("=" * 80)
print(f"🎯 STARTING BENCHMARK: {project_name.upper()} on AMD Ryzen 9 9950X (Zen 5)")
print(f" Repo: {repo_dir}")
print(f" Mitts binary: {MITTS_BIN}")
print(f" Sccache binary: {SCCACHE_BIN}")
print("=" * 80)
envs = setup_environments(project_name)
log_cmd = ["git", "log", "-n20", "--format=%h"]
all_commits = subprocess.check_output(log_cmd, cwd=repo_dir, text=True).strip().splitlines()
head_commit = all_commits[0]
commit_delta_1 = all_commits[1] if len(all_commits) > 1 else all_commits[0]
commit_delta_5 = all_commits[min(5, len(all_commits) - 1)]
commit_outside_s3 = all_commits[min(14, len(all_commits) - 1)]
results = {
"project": project_name,
"head_commit": head_commit,
"commit_outside_s3": commit_outside_s3,
"s1_cold_build": run_s1_cold_build(project_name, repo_dir, envs, repeats=3),
"s2_fast_noop": run_s2_fast_noop(project_name, repo_dir, envs, repeats=3),
"s3_git_history_replay": run_s3_git_history_replay(project_name, repo_dir, envs, num_commits=args.commits),
"s4_branch_hopping": run_s4_branch_hopping(project_name, repo_dir, envs, head_commit, commit_outside_s3),
}
commit_dist = (
[head_commit] * 4 +
[commit_delta_1] * 4 +
[commit_delta_5] * 2 +
[commit_outside_s3] * 2
)
results["s5a_cold_swarm"] = run_s5a_cold_swarm(
project_name, repo_dir, worktree_base_dir, envs, commit_dist
)
results["s5b_warm_swarm"] = run_s5b_warm_swarm(
project_name, repo_dir, worktree_base_dir, envs, commit_dist
)
out_file = Path(args.output) if args.output else (BENCHMARK_RESULTS_DIR / f"results_{project_name}_defensible.json")
out_file.parent.mkdir(parents=True, exist_ok=True)
with open(out_file, "w") as f:
json.dump(results, f, indent=2)
print(f"\n✅ Benchmark completed successfully! Full results saved to: {out_file}")
if __name__ == "__main__":
main()