46 lines
2.1 KiB
Python
Executable File
46 lines
2.1 KiB
Python
Executable File
#!/usr/bin/env python3
|
||
"""Runs the Go `go test -bench` suite and the Rust bench example
|
||
interleaved for several rounds and prints the best time per op of each.
|
||
|
||
rust/bench/micro.py GO_TUI_TEST GO_TREEMAP_TEST RUST_BENCH [ROUNDS]
|
||
|
||
Build the inputs with `go test -c ./internal/tui`, `go test -c
|
||
./internal/treemap` and `cargo build --release --example bench`. The Go tui
|
||
test binary must run from internal/tui, so run this from the repo root.
|
||
"""
|
||
import re, subprocess, sys
|
||
|
||
go_tui, go_tm, rust = sys.argv[1:4]
|
||
rounds = int(sys.argv[4]) if len(sys.argv) > 4 else 5
|
||
names = { # rust name -> go name
|
||
"treemap/Squarify(300)": "Squarify", "treemap/Neighbour(300)": "Neighbour",
|
||
"tui/BigColdFrame": "BigColdFrame", "tui/BigResize": "BigResize",
|
||
"tui/BigFlatDirCold": "BigFlatDirCold", "tui/BigNavigate": "BigNavigate",
|
||
"tui/BigFilter/size > 1MB": "BigFilter/size_>_1MB",
|
||
"tui/BigFilter/*.dat AND size > 500k": "BigFilter/*.dat_AND_size_>_500k",
|
||
"tui/BigFilter/path contains sub3": "BigFilter/path_contains_sub3",
|
||
}
|
||
unit = {"ns": 1e-9, "µs": 1e-6, "ms": 1e-3, "s": 1}
|
||
go_best, rust_best = {}, {}
|
||
|
||
def keep(d, k, v):
|
||
d[k] = min(d.get(k, v), v)
|
||
|
||
for _ in range(rounds):
|
||
for exe, cwd in ((go_tui, "internal/tui"), (go_tm, "internal/treemap")):
|
||
out = subprocess.run([exe, "-test.run=NONE", "-test.bench=.", "-test.benchtime=1s"], cwd=cwd, capture_output=True, text=True).stdout
|
||
for m in re.finditer(r"^Benchmark(\S+?)-\d+\s+\d+\s+([\d.]+) ns/op", out, re.M):
|
||
keep(go_best, m[1], float(m[2]) * 1e-9)
|
||
out = subprocess.run([rust], capture_output=True, text=True).stdout
|
||
for m in re.finditer(r"^(\S.*?)\s+\d+ ops\s+([\d.]+)(ns|µs|ms|s)/op", out, re.M):
|
||
keep(rust_best, m[1].strip(), float(m[2]) * unit[m[3]])
|
||
|
||
def fmt(s):
|
||
return f"{s * 1e6:.1f} µs" if s < 1e-3 else f"{s * 1e3:.2f} ms"
|
||
|
||
print(f"Best of {rounds} interleaved rounds\n")
|
||
print("| benchmark | Go | Rust | speed-up |\n|---|---:|---:|---:|")
|
||
for r, g in names.items():
|
||
if r in rust_best and g in go_best:
|
||
print(f"| {r} | {fmt(go_best[g])} | {fmt(rust_best[r])} | {go_best[g] / rust_best[r]:.2f}× |")
|