Add a PNG writer so the demos produce actual images. Two pieces:
- src/jolt/png.janet — the encoder (8-bit RGB, filter None, stored/uncompressed
DEFLATE so no compressor is needed; correct CRC32 + Adler32). It lives in Janet
because per-byte work in the overlay is far too slow (a byte-array aset loop is
~30s for 360k bytes, and CRC32 over even a tiny image would be worse). Janet's
bit ops are 32-bit signed, so the 32-bit-unsigned arithmetic is done with plain
number ops (doubles hold 2^32) plus byte-level bxor. Exposed to the overlay as
janet.png/* by importing it into eval_base's module-load-env.
- src/jolt/jolt/png.clj — the jolt.png overlay wrapper: image / put! / write. The
overlay only produces pixels; the host encodes them in one pass.
mandelbrot gets a `render` subcommand (jolt -m mandelbrot render out.png [size])
that colours count-point's escape counts; the numeric-arg bench path is untouched.
Verified end to end: macOS `sips` accepts the output (so CRC/zlib are valid).
png-test covers the encoder structure (signature/IHDR/IEND) and the overlay
round-trip.
Co-authored-by: Yogthos <yogthos@gmail.com>
The ray tracer is compute-bound and the three existing benches only cover
alloc / megamorphic-dispatch / collections. Add three axes the epic needs to
judge itself holistically:
- mono-dispatch: monomorphic protocol dispatch. Its jolt/JVM ratio (~110x) is
*worse* than megamorphic (~76x) — the JVM inline-caches a runtime-monomorphic
call site to near-free while jolt does a full registry dispatch (devirt only
fires on statically-proven receivers). Points at the call-site inline cache.
- mandelbrot: pure float compute, no alloc/dispatch. The floor at ~15x — native
arith already gets close to the JVM.
- fib: recursion, call + integer-arith overhead.
run.sh gains JVM=1, which runs each bench on JVM Clojure too and prints the
jolt/JVM ratio. collections sized up now that the map is a HAMT (jolt-684u).
README documents the axes and the current scorecard.
Co-authored-by: Yogthos <yogthos@gmail.com>