You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[perf regression] recursive self-calls slower on 0.5.1265 #7163
Functions that recurse (specific to self-recursion) run ~1.4–1.6x slower on 0.5.1265 than 0.5.1260.
Measurements (min ms, from-source builds, same host)
workload
0.5.1260
0.5.1265
ratio
fib(30) ×3 (~8M calls)
179
280
1.57
sumrec(1000) ×8000 (single self-call, ~8M)
236
322
1.36
flat 8M indirect non-recursive calls (control)
245
112
0.46 (faster)
iterative fib(30) ×3
~0
~0
—
Minimal reproduction
functionfib(n){returnn<2 ? n : (fib(n-1)+fib(n-2))|0;}functionwork(){vara=0;for(vark=0;k<3;k++)a=(a+fib(30))|0;returna|0;}work();varbest=1e9,c;for(varr=0;r<3;r++){vart=Date.now();c=work();vard=Date.now()-t;if(d<best)best=d;}console.log(best+" ms");// ~179 ms on 0.5.1260, ~280 ms on 0.5.1265
perry compile m.js -o m && ./m.
Environment
Perry 0.5.1260 (2e105ca) vs 0.5.1265 (a3b31c0d), cargo build --release -p perry
from tagged source, each linked to its own full runtime. macOS 27.0 arm64.
Audited this against current Perry and the later codegen history.
The exact JavaScript reproducer is still a recursive-numeric performance case (about 367-396 ms here on Perry 0.5.1482, Windows x86_64, with the expected 2496120 result), but this report is now superseded by #7244, which tracks the narrower actionable work: a sound recursive-numeric specialization.
The old speed came from emit_i64_specializations, which ran eligible number-typed self-recursive functions as i64. #7238 showed that path was unsound in two independent ways: it truncated fractional arguments on entry and diverged from JavaScript once intermediates crossed the exact-double range (and later i64 range). #7242 therefore removed it, explicitly measured the resulting Fibonacci cost, and opened #7244 for a guarded/deoptimizing replacement. That follow-up's acceptance criteria cover both restoring the performance and preserving the #7238 exactness tests.
I also A/B'd the current Phase-2 specialized ABI on the issue's verbatim repro; the best timings were 367 ms enabled and 370 ms disabled, so there is no separate modern ABI regression to fix here.
Closing this broad historical regression as superseded by #7244. No code change or version bump is appropriate on this issue.
Activity
proggeramlug commentedon Aug 12, 2026
Audited this against current Perry and the later codegen history.
The exact JavaScript reproducer is still a recursive-numeric performance case (about 367-396 ms here on Perry 0.5.1482, Windows x86_64, with the expected
2496120result), but this report is now superseded by #7244, which tracks the narrower actionable work: a sound recursive-numeric specialization.The old speed came from
emit_i64_specializations, which ran eligiblenumber-typed self-recursive functions as i64. #7238 showed that path was unsound in two independent ways: it truncated fractional arguments on entry and diverged from JavaScript once intermediates crossed the exact-double range (and later i64 range). #7242 therefore removed it, explicitly measured the resulting Fibonacci cost, and opened #7244 for a guarded/deoptimizing replacement. That follow-up's acceptance criteria cover both restoring the performance and preserving the #7238 exactness tests.I also A/B'd the current Phase-2 specialized ABI on the issue's verbatim repro; the best timings were 367 ms enabled and 370 ms disabled, so there is no separate modern ABI regression to fix here.
Closing this broad historical regression as superseded by #7244. No code change or version bump is appropriate on this issue.