#!/usr/bin/env -S uv run --script # # /// script # requires-python = ">=3.12" # dependencies = [] # /// # Exports latest Criterion results to a .csv file. import argparse import csv from datetime import date import json import subprocess from pathlib import Path def parse_args(): parser = argparse.ArgumentParser(description="Convert latest Criterion results to CSV.") parser.add_argument("suffix", help="CSV filename suffix, e.g. 9800x3d") args = parser.parse_args() return args def filename(args): cmd = ["git", "rev-parse", "--short=16", "HEAD"] commit = subprocess.check_output(cmd, text=True).strip() return f"{commit}_{args.suffix}.csv" def get_save_path(args): measurements = Path(__file__).resolve().parent return measurements / filename(args) def parse_data(args): script_dir = Path(__file__).resolve() project_root = script_dir.parents[1] criterion = project_root / "target/criterion" files = list(criterion.glob("size *, fft v8/new/estimates.json")) latest_date = max(date.fromtimestamp(path.stat().st_mtime) for path in files) data = [] for path in files: # Ignore sizes left over from runs on earlier dates. if date.fromtimestamp(path.stat().st_mtime) != latest_date: continue size = int(path.parent.parent.name.split(",")[0].split()[1]) row = [size] for implementation in ["reference", "fft v8"]: estimates_path = criterion / f"size {size}, {implementation}/new/estimates.json" assert date.fromtimestamp(estimates_path.stat().st_mtime) == latest_date estimates = json.loads(estimates_path.read_text()) row.append(estimates["slope"]["point_estimate"]) data.append(row) return sorted(data) def main(): args = parse_args() data = parse_data(args) with open(get_save_path(args), "w", newline="", encoding="utf-8") as file: writer = csv.writer(file, lineterminator="\n") writer.writerow(["Input length", "rustfft", "vfft (fft v8)"]) writer.writerows(data) print(filename(args)) if __name__ == "__main__": main()