Context
urdr (pyrex41/urdr @ 45ff3c1) drives all four Shen ports through Bifrost with exact-golden suites. shen-lua passes semantically but the wall-clock tax is large. Pins: shen-lua @ c85ad7e (bin/shen, LuaJIT 2.1 rolling, kernel 41.2); shen-cl @ 8df94be. Host: macOS arm64.
1. Cold start (largest single fix — PR #45)
Trivial script ((output "hi~%")): shen-lua ~1.5s vs shen-cl ~13ms. Breakdown: require boot 0.003s, load_kernel 0.11s (with the kernel bytecode cache), initialise 1.77s — almost all of it load_stdlib() recompiling StLib from Shen sources every boot, because 19/21 StLib files were fasl-uncacheable: every (define) triggers (set shen.*lambdatable* ...) whose entries hold live curried lambdas, and kdata_ser bails (unserializable KDATA value: function, boot.lua:254), poisoning the whole file's fasl.
Fixed in PR #45 (record lambdatable deltas by name, rebuild via shen.lambda-entry on replay): warm startup 1.5s → 0.34s, 21/21 StLib files cacheable, 500/0 specs + 134/0 certification green.
Note for benchmark hygiene: SHEN_KERNEL_CACHE=off/SHEN_FASL=off (set in urdr's original benchmark env for other ports) also disable shen-lua's caches and add ~0.5-0.7s — earlier urdr numbers include that.
2. Suite compute: ~12x CL on pure-Shen SHA-256 (structural)
urdr's dominant cost is portable software SHA-256 + bigints in pure Shen. shen/tests/prng/run-tests.shen (29 tests): shen-cl 0.76s vs shen-lua 8.8-12s. urdr search suite: CL 6.25s vs lua 72.6s (~12x). JIT is on and load-bearing (SHEN_JIT=off → 37s on prng). With PR #45 the fasl covers load cost, but the digest loops themselves remain ~12x. If there's headroom (e.g. avoiding boxed number churn on hot arithmetic, jit.opt tuning for these trace shapes) this workload is a good target; otherwise fine to call it structural and close.
3. -q hushes ALL output, so batch/golden runners can't use it
-q sets *hush*, which on 41.2 gates pr itself — a suite run under -q prints nothing, including the suite's own (output ...) results, so exact-golden comparison is impossible. Meanwhile the default mode prints ~100 load-echo lines on urdr suites (vs 4-17 on the other ports), which inflates diffs against other ports' output. A mode that silences only the load echo (per-form value/type banners) while leaving user (output) alive would be ideal for suite runners like Bifrost.
Repro
printf '(output "hi~%%")' > /tmp/tiny.shen
/usr/bin/time -p bin/shen /tmp/tiny.shen # startup
cd urdr && /usr/bin/time -p $SHEN_LUA shen/tests/prng/run-tests.shen # SHA workload
Context
urdr (
pyrex41/urdr@ 45ff3c1) drives all four Shen ports through Bifrost with exact-golden suites. shen-lua passes semantically but the wall-clock tax is large. Pins: shen-lua @ c85ad7e (bin/shen, LuaJIT 2.1 rolling, kernel 41.2); shen-cl @ 8df94be. Host: macOS arm64.1. Cold start (largest single fix — PR #45)
Trivial script (
(output "hi~%")): shen-lua ~1.5s vs shen-cl ~13ms. Breakdown:require boot0.003s,load_kernel0.11s (with the kernel bytecode cache),initialise1.77s — almost all of itload_stdlib()recompiling StLib from Shen sources every boot, because 19/21 StLib files were fasl-uncacheable: every(define)triggers(set shen.*lambdatable* ...)whose entries hold live curried lambdas, andkdata_serbails (unserializable KDATA value: function, boot.lua:254), poisoning the whole file's fasl.Fixed in PR #45 (record lambdatable deltas by name, rebuild via
shen.lambda-entryon replay): warm startup 1.5s → 0.34s, 21/21 StLib files cacheable, 500/0 specs + 134/0 certification green.Note for benchmark hygiene:
SHEN_KERNEL_CACHE=off/SHEN_FASL=off(set in urdr's original benchmark env for other ports) also disable shen-lua's caches and add ~0.5-0.7s — earlier urdr numbers include that.2. Suite compute: ~12x CL on pure-Shen SHA-256 (structural)
urdr's dominant cost is portable software SHA-256 + bigints in pure Shen.
shen/tests/prng/run-tests.shen(29 tests): shen-cl 0.76s vs shen-lua 8.8-12s. urdr search suite: CL 6.25s vs lua 72.6s (~12x). JIT is on and load-bearing (SHEN_JIT=off→ 37s on prng). With PR #45 the fasl covers load cost, but the digest loops themselves remain ~12x. If there's headroom (e.g. avoiding boxed number churn on hot arithmetic, jit.opt tuning for these trace shapes) this workload is a good target; otherwise fine to call it structural and close.3.
-qhushes ALL output, so batch/golden runners can't use it-qsets*hush*, which on 41.2 gatespritself — a suite run under-qprints nothing, including the suite's own(output ...)results, so exact-golden comparison is impossible. Meanwhile the default mode prints ~100 load-echo lines on urdr suites (vs 4-17 on the other ports), which inflates diffs against other ports' output. A mode that silences only the load echo (per-form value/type banners) while leaving user(output)alive would be ideal for suite runners like Bifrost.Repro