Performance
- Native
fcmpfor numeric comparisons: known-numeric operands emit Craneliftfcmpinstead ofjs_jsvalue_compareruntime function call — mandelbrot 30% faster compile_condition_to_boolfast path: numericComparein loop/if conditions produces I8 boolean directly, skipping NaN-box round-trip- Short-circuit
&&/||: proper branching incompile_condition_to_boolinstead of always-evaluate-both withband/bor - In-place string append with capacity tracking:
js_string_appendreuses allocation when refcount=1 and capacity allows — string_concat benchmark 125x faster (900ms → 7ms) - Deferred module-var write-back in loops: skip global stores inside simple loops (no function calls), flush at exit
- Method inlining for small class methods
Bug Fixes
- Linux linker no longer requires PulseAudio for non-UI programs —
-lpulse-simple -lpulsemoved behindneeds_uiguard (GH-8) perry run .now works — positional args parsed flexibly so non-platform values are treated as input path instead of erroring
Benchmarks
Full benchmark overhaul — all benchmarks rerun with Node.js v25 and Bun 1.3, with Bun included in every entry. README now shows the full picture with context explaining both wins and losses:
| Category | Benchmarks | Perry vs Node | Perry vs Bun |
|---|---|---|---|
| Perry wins | fibonacci, array_read, object_create | 2.0–3.5x faster | 1.1–4.5x faster |
| Competitive | method_calls, prime_sieve, string_concat | 0.3–0.7x | 0.1–0.6x |
| V8/Bun leads | mandelbrot, matrix_multiply, math_intensive | 0.1–0.6x | 0.1–0.6x |
V8 leads on f64-intensive workloads due to SIMD auto-vectorization and decades of JIT optimization. Perry excels at function calls, recursion, and sequential memory access.