Skip to content

[perf regression] recursive self-calls slower on 0.5.1265 #7163

Closed as not planned

Description

@dlee

What happened

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

function fib(n) { return n < 2 ? n : (fib(n - 1) + fib(n - 2)) | 0; }
function work() { var a = 0; for (var k = 0; k < 3; k++) a = (a + fib(30)) | 0; return a | 0; }
work();
var best = 1e9, c;
for (var r = 0; r < 3; r++) { var t = Date.now(); c = work(); var d = 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.

Activity

  1. proggeramlug commented on Aug 12, 2026

    @proggeramlug
    Contributor

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions