Chez re-host spike: substrate ceiling vs Janet (fib/mandelbrot)

Hand-translate the two compute benches into the Scheme a jolt->Chez backend
would emit, to localize the execution-substrate ceiling without porting the RT.

fib 30: 246.6 -> 5.2 ms (~47x, fixnum). mandelbrot 200: 166.3 -> 13.4 ms
(~12.4x) ONLY with flonum-specialized ops; generic float ops box every flonum
and stay ~1.7x. 13.4 ms matches jolt's JOLT_CGEN C result, so Chez's native
compiler reaches the C ceiling with no cc step, REPL intact.

Size: Chez base 2.9 MB (AOT) / 4.0 MB (dynamic) vs Janet 2.21. Memory: Chez
~32-49 MB fixed baseline vs Janet ~12 MB (the one regression). RT-bound axes
(collections/binary-trees, where Chez's generational GC should help) not yet
measured. See spike/chez/RESULTS.md.
This commit is contained in:
Yogthos 2026-06-17 12:07:35 -04:00
parent 3c853429f9
commit 0087763dc9
4 changed files with 216 additions and 0 deletions

View file

@ -0,0 +1,45 @@
;; mandelbrot, flonum-specialized — what a type-aware jolt->Chez backend would
;; emit (fl*/fl+/fl< unbox; fx ops for the integer counter). This is the real
;; substrate ceiling vs the generic version (which boxes every flonum).
;; chez --script mandelbrot-fl.ss [n=200] [optlevel=3]
(import (chezscheme))
(optimize-level
(let ((a (command-line-arguments)))
(if (and (pair? a) (pair? (cdr a))) (string->number (cadr a)) 3)))
(define (count-point cr ci cap)
(let loop ((i 0) (zr 0.0) (zi 0.0))
(if (or (fx>= i cap) (fl> (fl+ (fl* zr zr) (fl* zi zi)) 4.0))
i
(loop (fx+ i 1)
(fl+ (fl- (fl* zr zr) (fl* zi zi)) cr)
(fl+ (fl* 2.0 (fl* zr zi)) ci)))))
(define (run n)
(let ((cap 200) (nd (fixnum->flonum n)))
(let loopy ((y 0) (acc 0))
(if (fx< y n)
(let* ((ci (fl- (fl/ (fl* 2.0 (fixnum->flonum y)) nd) 1.0))
(row (let loopx ((x 0) (a 0))
(if (fx< x n)
(let ((cr (fl- (fl/ (fl* 2.0 (fixnum->flonum x)) nd) 1.5)))
(loopx (fx+ x 1) (fx+ a (count-point cr ci cap))))
a))))
(loopy (fx+ y 1) (fx+ acc row)))
acc))))
(define (now-ns)
(let ((t (current-time 'time-monotonic)))
(+ (* (time-second t) 1000000000) (time-nanosecond t))))
(let* ((a (command-line-arguments))
(n (if (pair? a) (string->number (car a)) 200)))
(run n) (run n)
(let loop ((k 0) (acc '()))
(if (< k 3)
(let* ((t0 (now-ns)) (r (run n)) (ms (/ (- (now-ns) t0) 1000000.0)))
(loop (+ k 1) (cons ms acc)))
(begin
(printf "mandelbrot-fl n ~a result ~a\n" n (run n))
(printf "runs: ~a\n" (reverse acc))
(printf "mean: ~a ms\n" (exact->inexact (/ (apply + acc) 3.0)))))))