#!/usr/bin/env python3 """Run an FZL VM benchmark and report wall-clock timing statistics.""" import argparse import statistics import subprocess import sys import time def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--runs", type=int, default=7, help="measured runs") parser.add_argument("--warmup", type=int, default=2, help="warm-up runs") parser.add_argument("--max-iter", type=int, default=2_000_000) parser.add_argument("--vm", required=True, help="path to the fz executable") parser.add_argument("--program", required=True, help="compiled .fzb program") args = parser.parse_args() if args.runs < 1 or args.warmup < 0 or args.max_iter < 1: parser.error("runs/max-iter must be positive and warmup must be non-negative") command = [args.vm, "--max-iter", str(args.max_iter), args.program] for _ in range(args.warmup): result = subprocess.run(command, capture_output=True, text=True) if result.returncode != 0: sys.stderr.write(result.stdout) sys.stderr.write(result.stderr) raise SystemExit(result.returncode) measurements = [] for _ in range(args.runs): start = time.perf_counter() result = subprocess.run( command, capture_output=True, text=True ) elapsed = time.perf_counter() - start if result.returncode != 0: sys.stderr.write(result.stdout) sys.stderr.write(result.stderr) raise SystemExit(result.returncode) measurements.append(elapsed) print(f"Runs: {args.runs} (warm-up: {args.warmup})") print(f"Median: {statistics.median(measurements):.6f} s") print(f"Mean: {statistics.mean(measurements):.6f} s") print(f"Min: {min(measurements):.6f} s") print(f"Max: {max(measurements):.6f} s") if __name__ == "__main__": main()