The jolt-vs-hand-Janet-vs-JVM mandelbrot comparison splits the 15.4x floor into two layers: a Janet-VM floor (~10.8x JVM, optimal while-loop Janet over unboxed doubles — only native codegen moves it) plus a ~1.43x jolt loop- lowering overhead on top. The overhead is entirely the loop/recur -> recursive- closure-called-per-iteration lowering; hand-Janet written the same way matches jolt, while a while+var/set version is 1.43x faster. So a cheap backend win (jolt-v28u) sits above the structural native-codegen lever. Adds the spike artifacts under bench/ and the results writeup; marks the spike done in the handoff. No source changes. Co-authored-by: Yogthos <yogthos@gmail.com>
53 lines
1.4 KiB
Text
53 lines
1.4 KiB
Text
# mandelbrot — hand-written idiomatic Janet, same nested loop as bench/mandelbrot.clj.
|
|
# This is the "optimal Janet" leg of the foundational-runtime spike (jolt-5vsp):
|
|
# comparing jolt-emitted Janet vs this vs JVM localizes the 15x compute floor —
|
|
# jolt-backend overhead vs the Janet VM's own floor.
|
|
#
|
|
# janet bench/mandelbrot-hand.janet 200
|
|
|
|
(defn count-point [cr ci cap]
|
|
(var i 0)
|
|
(var zr 0.0)
|
|
(var zi 0.0)
|
|
(while (and (< i cap) (<= (+ (* zr zr) (* zi zi)) 4.0))
|
|
(def nzr (+ (- (* zr zr) (* zi zi)) cr))
|
|
(def nzi (+ (* 2.0 (* zr zi)) ci))
|
|
(set zr nzr)
|
|
(set zi nzi)
|
|
(++ i))
|
|
i)
|
|
|
|
(defn run [n]
|
|
(def cap 200)
|
|
(def nd (* 1.0 n))
|
|
(var acc 0)
|
|
(var y 0)
|
|
(while (< y n)
|
|
(def ci (- (/ (* 2.0 y) nd) 1.0))
|
|
(var x 0)
|
|
(var a 0)
|
|
(while (< x n)
|
|
(def cr (- (/ (* 2.0 x) nd) 1.5))
|
|
(set a (+ a (count-point cr ci cap)))
|
|
(++ x))
|
|
(set acc (+ acc a))
|
|
(++ y))
|
|
acc)
|
|
|
|
(defn main [& args]
|
|
(def n (if (> (length args) 1) (scan-number (get args 1)) 1000))
|
|
# warmup
|
|
(repeat 2 (run (div n 2)))
|
|
(def runs 3)
|
|
(def times @[])
|
|
(var last-r 0)
|
|
(repeat runs
|
|
(def t0 (os/clock))
|
|
(def r (run n))
|
|
(def ms (* 1000.0 (- (os/clock) t0)))
|
|
(set last-r r)
|
|
(array/push times ms))
|
|
(def mean (/ (sum times) runs))
|
|
(printf "mandelbrot n %d result %d" n last-r)
|
|
(print "runs: " (string/join (map |(string (/ (math/round (* $ 10.0)) 10.0)) times) " "))
|
|
(printf "mean: %.1f ms" mean))
|