core: lazy realization is shared across walks (once-only effects); pmap family
Every walk over a lazy seq created FRESH wrapper tables around the shared rest-thunks (ls-rest, ls-seq/ls-count, realize-for-iteration, the printers, reduce — each had its own make-lazy-seq loop), so independent walks re-ran the thunks: side effects duplicated, and a doall'd seq of futures was re-spawned serially by the deref walk. Every walker now goes through ls-rest-cached, which memoizes the rest wrapper on its node — thunks run exactly once, as in Clojure. Costs ~10% on walk-heavy benches (the per-node cache get/put — Clojure's LazySeq pays the same); net still -9% vs the pre-linear-walks baseline. Three regression rows pin once-only effects and value stability across walks. On top of that: pmap/pcalls/pvalues (jolt-oeu) over the real-thread futures — spawn-all-then-deref (the once-only fix is what makes the doall actually mean that), snapshot semantics documented, multi-coll arity via the canonical vector-zip. System/currentTimeMillis + nanoTime land as System statics (the realtime clock — os/time is whole seconds, which quantized every elapsed measurement to 1000ms). Seven pmap rows incl. a generous- margin parallelism check (4 x 200ms sleeps under 700ms after warmup).
This commit is contained in:
parent
599c0468f7
commit
4a1a9e3aec
8 changed files with 78 additions and 12 deletions
|
|
@ -49,3 +49,16 @@
|
|||
# The future's own return value still reflects the swap on its copy.
|
||||
["future sees its own mutation"
|
||||
"1" "(let [a (atom 0)] (deref (future (swap! a inc))))"])
|
||||
|
||||
# pmap/pcalls/pvalues over the real-thread futures: spawn-all-then-deref, so
|
||||
# independent work overlaps; snapshot semantics (pure fns only). The wall-time
|
||||
# row uses generous margins (4 x 150ms in parallel vs 600ms serial).
|
||||
(defspec "clojure.core / pmap family"
|
||||
["pmap values in order" "[2 3 4]" "(vec (pmap inc [1 2 3]))"]
|
||||
["pmap multi-coll" "[5 7 9]" "(vec (pmap + [1 2 3] [4 5 6]))"]
|
||||
["pmap empty" "()" "(pmap inc [])"]
|
||||
["pmap is parallel" "true"
|
||||
"(do (deref (future :warmup)) (let [t0 (System/currentTimeMillis)] (dorun (pmap (fn [_] (Thread/sleep 200)) [1 2 3 4])) (< (- (System/currentTimeMillis) t0) 700)))"]
|
||||
["pcalls" "[1 2]" "(vec (pcalls (fn [] 1) (fn [] 2)))"]
|
||||
["pvalues" "[3 7]" "(vec (pvalues (+ 1 2) (+ 3 4)))"]
|
||||
["snapshot semantics" "0" "(let [a (atom 0)] (dorun (pmap (fn [_] (swap! a inc)) [1 2])) (deref a))"])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue