core: AOT context image — init-cached recovers the bootstrap cost across processes
init in compile mode is ~2.4 s (tier loading, analyzer self-compile, macro recompilation), paid by every process that builds a ctx from source — each jpm-test file, embedders, workers. init-cached marshals the built ctx to a disk image (same root-env dicts as snapshot/fork) and later processes unmarshal it in ~5 ms, any process: nothing from the baking process is needed at load. The cache key fingerprints the embedded .clj stdlib (which covers jolt-core: analyzer, IR, core tiers), the .janet seed sources next to the module, the janet version, the init opts, and the env knobs that shape a ctx (JOLT_PATH/ MUTABLE/AOT_CORE/FEATURES) — any change rebuilds. Corrupt or non-ctx images fall back to a rebuild (unmarshal of garbage can 'succeed' with a scalar, so the shape is checked, not just the throw). Writes are atomic (tmp + rename) so racing cold starts never publish a torn image. JOLT_NO_IMAGE_CACHE=1 opts out; JOLT_IMAGE_CACHE_DIR overrides the location (default TMPDIR). Test consumers switch to init-cached (harness, suite-worker, conformance, the behavioral unit/integration tests); tests that validate the bootstrap itself (bootstrap-fixpoint, staged-bootstrap, aot round-trip, direct-linking) and the deps tests (tmp-dir :paths would fragment the key) keep real init. Full jpm test: 2:46 -> 1:58 (~29%). New ctx-image-test covers cold/warm, cross-process load (subprocess runs defn/redef/macros/protocols/multimethods off the baked image), per-opts keying, and corrupt-image fallback.
This commit is contained in:
parent
bf885078f9
commit
0e3584884f
24 changed files with 222 additions and 64 deletions
|
|
@ -13,7 +13,7 @@
|
|||
# 1. Basic hash-map construction and access
|
||||
# ============================================================
|
||||
(print "1: hash-map construction...")
|
||||
(let [ctx (init)]
|
||||
(let [ctx (init-cached)]
|
||||
(def m1 (ct-eval ctx "(hash-map :a 1)"))
|
||||
(assert (not (nil? m1)) "hash-map returns non-nil")
|
||||
(assert (= true (ct-eval ctx "(map? (hash-map :a 1))")) "map? returns true for PHM")
|
||||
|
|
@ -29,7 +29,7 @@
|
|||
# 2. assoc and dissoc
|
||||
# ============================================================
|
||||
(print "2: assoc/dissoc...")
|
||||
(let [ctx (init)]
|
||||
(let [ctx (init-cached)]
|
||||
(assert (= true (ct-eval ctx "(= (assoc (hash-map :a 1) :b 2) (hash-map :a 1 :b 2))")) "assoc add")
|
||||
(assert (= true (ct-eval ctx "(= (assoc (hash-map :a 1) :a 99) (hash-map :a 99))")) "assoc replace")
|
||||
(assert (= true (ct-eval ctx "(= (dissoc (hash-map :a 1 :b 2) :a) (hash-map :b 2))")) "dissoc")
|
||||
|
|
@ -41,7 +41,7 @@
|
|||
# 3. keys, vals, merge
|
||||
# ============================================================
|
||||
(print "3: keys/vals/merge...")
|
||||
(let [ctx (init)]
|
||||
(let [ctx (init-cached)]
|
||||
(assert (= 2 (ct-eval ctx "(count (keys (hash-map :a 1 :b 2)))")) "keys count")
|
||||
(assert (= 2 (ct-eval ctx "(count (vals (hash-map :a 1 :b 2)))")) "vals count")
|
||||
(assert (= true (ct-eval ctx "(= (merge (hash-map :a 1) (hash-map :b 2)) (hash-map :a 1 :b 2))")) "merge"))
|
||||
|
|
@ -52,7 +52,7 @@
|
|||
# 4. Empty and seq
|
||||
# ============================================================
|
||||
(print "4: empty? and seq...")
|
||||
(let [ctx (init)]
|
||||
(let [ctx (init-cached)]
|
||||
(assert (= true (ct-eval ctx "(empty? (hash-map))")) "empty? true")
|
||||
(assert (= false (ct-eval ctx "(empty? (hash-map :a 1))")) "empty? false")
|
||||
(assert (= 1 (ct-eval ctx "(count (seq (hash-map :a 1)))")) "seq count"))
|
||||
|
|
@ -62,7 +62,7 @@
|
|||
# 5. Larger maps
|
||||
# ============================================================
|
||||
(print "5: larger maps...")
|
||||
(let [ctx (init)]
|
||||
(let [ctx (init-cached)]
|
||||
(eval-string ctx "
|
||||
(def big-map
|
||||
(reduce (fn [m i] (assoc m (keyword (str \"k\" i)) i))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue