test: ~11x faster gate — ctx snapshot/fork + parallel suite battery

The gate spent almost all its time rebuilding identical contexts: init is
~50 ms interpreted / ~900 ms compiled (tier loading, analyzer build, macro
recompilation), and both the conformance harness and the spec harness built a
fresh ctx PER CASE — 269 cases x 3 modes for conformance alone (~285 s), and
~1500 spec cases (~90 s). The suite battery additionally ran its 234 worker
subprocesses sequentially (~100 s incl. 5 x 6 s timeout files).

- api: snapshot/fork — marshal a fully-built ctx once (reverse-lookup dicts
  from root-env, built at module load before any ctx exists), unmarshal cheap
  fully-isolated deep copies (~2 ms). A fork shares nothing mutable with its
  siblings, so per-case isolation is preserved exactly.
- conformance: one init per mode + fork per case (self-host pre-builds the
  analyzer before snapshotting). 285 s -> 5 s, same 269x3 results.
- spec harness: jeval/run-spec/expect-throws fork from one lazy module-level
  snapshot. Spec sweep ~90 s -> 9 s, all pass.
- clojure-test-suite: run the per-file worker subprocesses through a
  token-channel worker pool (default 4, JOLT_SUITE_WORKERS to override,
  capped at 8). 17.5 s with counts identical to the sequential run
  (4046/520/116, 5 timeouts).

Full gate wall-clock: ~8 min -> 43 s, everything green (conformance 269x3,
fallback-zero, fixpoint, self-host, sci, staged, suite >= 4034/67, all
specs+unit).
This commit is contained in:
Yogthos 2026-06-10 09:11:58 -04:00
parent 3e9fe8d0fb
commit 920fafe032
4 changed files with 76 additions and 11 deletions

View file

@ -22,14 +22,25 @@
(use ../../src/jolt/api)
# Every case still gets a fully-isolated context, but via api/fork (~2 ms deep
# copy of a snapshotted ctx) instead of a fresh init (~50 ms) — the same
# behavior, ~25x faster across the ~1500 spec cases. Built lazily so harness
# importers that never eval (or that only use run-spec) pay it once at most.
(var- base-snap nil)
(defn fresh-ctx
"A fresh, fully-isolated interpret-mode context (cheap fork of one shared init)."
[]
(when (nil? base-snap) (set base-snap (snapshot (init))))
(fork base-snap))
(defn jeval
"Evaluate a Clojure source string in a fresh context, normalizing persistent
vectors/lists to Janet tuples so results compare with `deep=`/tuple literals."
[s]
(normalize-pvecs (eval-string (init) s)))
(normalize-pvecs (eval-string (fresh-ctx) s)))
(defn- show [s]
(let [r (protect (eval-string (init) s))]
(let [r (protect (eval-string (fresh-ctx) s))]
(if (= (r 0) true)
(string/format "%q" (normalize-pvecs (r 1)))
(string "<error: " (r 1) ">"))))
@ -44,11 +55,11 @@
(def expected (in case 1))
(def actual (in case 2))
(if (= expected :throws)
(let [r (protect (eval-string (init) actual))]
(let [r (protect (eval-string (fresh-ctx) actual))]
(if (= (r 0) false)
(++ pass)
(array/push fails [label "expected an error, got a value"])))
(let [r (protect (eval-string (init) (string "(= " expected " " actual ")")))]
(let [r (protect (eval-string (fresh-ctx) (string "(= " expected " " actual ")")))]
(cond
(not= (r 0) true) (array/push fails [label (string "errored: " (r 1))])
(= (r 1) true) (++ pass)
@ -79,5 +90,5 @@
(defn expect-throws
"Assert that evaluating Clojure `s` raises an error."
[s]
(let [r (protect (eval-string (init) s))]
(let [r (protect (eval-string (fresh-ctx) s))]
(assert (= (r 0) false) (string "expected an error for: " s))))