The JIT that runs makepad apps from source: lexer, front end, type checker, lazy borrow checker (Gandalf; `--check-first` opts in), codegen, session and warm/cold caches keyed by compiler stamp, provided crates bound late, startup images, live patching. User-facing name is `makepad run` (binary `makepad`, MAKEPAD_RUN_* env, ~/.makepad-run); libs/relax stays the internal library name. `makepad check` reports rustc-style diagnostics with rustc error codes and checks a whole workspace (`--workspace`). Runs on macOS, Linux, Windows and Android. makepad-remote: one tool schema for apps and the WM (app/1): grabs, captures, traces, frame profiles and tweaks. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
69 lines
3.8 KiB
Python
69 lines
3.8 KiB
Python
#!/usr/bin/env python3
|
|
"""Interpreter vs JIT vs rustc on bench_rt kernels (ios-interp research prototype).
|
|
Usage: cmp.py <makepad binary> <rustc bench binary> [kernel ...]; ROUNDS (default 3) interleaved rounds,
|
|
best per mode. Modes: rustc; jit-o1 (MAKEPAD_RUN_O3=0 MAKEPAD_RUN_O1=0); jit-o3 (default tiers, BENCH_WARM_MS=2500);
|
|
interp (MAKEPAD_RUN_INTERP=all, O3/O1 off). Prints a markdown table of best ms and ratios, checksums compared."""
|
|
import os, re, subprocess, sys
|
|
here = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
mk, native = sys.argv[1], sys.argv[2]
|
|
src = open(os.path.join(here, "src/main.rs")).read()
|
|
names = sys.argv[3:] or re.findall(r'\("(\w+)", \w+\),', src)
|
|
rounds = int(os.environ.get("ROUNDS", "3"))
|
|
base = dict(os.environ, MAKEPAD_RUN_STD=os.path.join(here, "../std"), MAKEPAD_RUN_CACHE="off",
|
|
BENCH_FONT=os.path.normpath(os.path.join(here, "../../../../widgets/resources/IBMPlexSans-Text.ttf")))
|
|
modes = {
|
|
"rustc": None,
|
|
"jit-o1": dict(MAKEPAD_RUN_O3="0", MAKEPAD_RUN_O1="0"),
|
|
"jit-o3": dict(BENCH_WARM_MS="2500"),
|
|
"interp": dict(MAKEPAD_RUN_INTERP="all", MAKEPAD_RUN_INTERP_STATS="1", MAKEPAD_RUN_O3="0", MAKEPAD_RUN_O1="0"),
|
|
# no machine code at all: precompiled glue, every function interpreted
|
|
"nocodegen": dict(MAKEPAD_RUN_NO_CODEGEN="1", MAKEPAD_RUN_INTERP_STATS="1"),
|
|
# A/B of the lowering's own clean-ups: no constant-branch folding and no loop-constant preload
|
|
"interp-plain": dict(MAKEPAD_RUN_INTERP="all", MAKEPAD_RUN_INTERP_STATS="1", MAKEPAD_RUN_O3="0", MAKEPAD_RUN_O1="0", MAKEPAD_RUN_INTERP_NOFOLD="1"),
|
|
}
|
|
want = os.environ.get("MODES")
|
|
if want:
|
|
modes = {k: v for k, v in modes.items() if k in want.split(",")}
|
|
else:
|
|
modes.pop("interp-plain")
|
|
modes.pop("nocodegen")
|
|
def one(mode, n):
|
|
if modes[mode] is None:
|
|
cmd, env = ["nice", "-n", "5", native, n], base
|
|
else:
|
|
cmd, env = ["nice", "-n", "5", mk, "run", "--quiet", "relax-bench-rt", "--", n], dict(base, **modes[mode])
|
|
try:
|
|
out = subprocess.run(cmd, cwd=here, env=env, capture_output=True, text=True, timeout=600)
|
|
except subprocess.TimeoutExpired:
|
|
return None, None, "timeout"
|
|
m = re.search(r"^\| " + n + r" ([\d.]+) (\d+)$", out.stdout, re.M)
|
|
st = re.search(r"makepad-run interp: (\d+) fns interpreted .*?, (\d+) stayed native(.*)", out.stderr)
|
|
if not m:
|
|
return None, None, (out.stdout + out.stderr)[-300:].replace("\n", " ")
|
|
return float(m.group(1)), m.group(2), (st.group(0) if st else "")
|
|
res = {}
|
|
for r in range(rounds):
|
|
for n in names:
|
|
for mode in modes:
|
|
t, ck, note = one(mode, n)
|
|
k = (n, mode)
|
|
if t is None:
|
|
res.setdefault(k, (None, None, note))
|
|
print("#", n, mode, "FAILED", note, flush=True)
|
|
continue
|
|
old = res.get(k)
|
|
if old is None or old[0] is None or t < old[0]:
|
|
res[k] = (t, ck, note)
|
|
print("# round", r, n, {m: res.get((n, m), (None,))[0] for m in modes}, flush=True)
|
|
cols = list(modes)
|
|
print("| kernel | " + " | ".join(c + " ms" for c in cols) + " | interp/jit-o1 | interp/jit-o3 | interp/rustc | sums | interp coverage |")
|
|
print("|---" * (len(cols) + 6) + "|")
|
|
for n in names:
|
|
row = [res.get((n, c), (None, None, ""))for c in cols]
|
|
t = {c: res.get((n, c), (None,))[0] for c in cols}
|
|
def ratio(a, b):
|
|
return "%.2f" % (t[a] / t[b]) if t.get(a) and t.get(b) else "-"
|
|
sums = {r[1] for r in row if r[1]}
|
|
cov = res.get((n, "interp"), (None, None, ""))[2]
|
|
cov = re.sub(r"makepad-run interp: ", "", cov or "")[:160]
|
|
print("| %s | %s | %s | %s | %s | %s | %s |" % (n, " | ".join("%.3f" % x[0] if x[0] else "FAIL" for x in row), ratio("interp", "jit-o1"), ratio("interp", "jit-o3"), ratio("interp", "rustc"), "ok" if len(sums) == 1 else "DIFF", cov))
|