from __future__ import annotations
import argparse
import platform
import subprocess
import sys
from pathlib import Path
def os_slug() -> str:
system = platform.system().lower()
if system.startswith("windows"):
return "windows"
if system.startswith("linux"):
return "linux"
if system.startswith("darwin"):
return "macos"
return "other"
def cargo_command(surface: str) -> list[str]:
if surface == "neutral":
return [
"cargo",
"bench",
"--bench",
"cold_start",
"--bench",
"compaction",
"--bench",
"projection_latency",
"--bench",
"subscription_fanout",
"--bench",
"write_throughput",
]
if surface == "redb":
return ["cargo", "bench", "--features", "redb", "--bench", "projection_latency"]
if surface == "lmdb":
return ["cargo", "bench", "--features", "lmdb", "--bench", "projection_latency"]
raise ValueError(f"unsupported surface: {surface}")
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--surface", required=True, choices=["neutral", "redb", "lmdb"])
parser.add_argument("--save", action="store_true")
parser.add_argument("--compare", action="store_true")
args = parser.parse_args()
if args.save and args.compare:
parser.error("--save and --compare are mutually exclusive")
baseline = f"{os_slug()}-{args.surface}-v3"
command = cargo_command(args.surface)
if args.save:
command += ["--", "--save-baseline", baseline]
print(f"Running {args.surface} benchmarks and saving baseline {baseline}...")
elif args.compare:
target_dir = Path("target") / "criterion"
baseline_exists = target_dir.exists() and any(
path.is_dir() and path.name == baseline for path in target_dir.rglob(baseline)
)
if not baseline_exists:
print(
f"Baseline {baseline} does not exist yet. Run "
f"'python ./scripts/bench-report --surface {args.surface} --save' first."
)
return 1
command += ["--", "--baseline", baseline]
print(f"Comparing {args.surface} benchmarks against baseline {baseline}...")
else:
print(f"Running {args.surface} benchmarks...")
print(f"Baseline name: {baseline}")
return subprocess.call(command)
if __name__ == "__main__":
sys.exit(main())