Lean Kernel Arena / perf/let-ladder

Test "perf/let-ladder"

Expected: 👍 accept · Size: 457.3 KB · Lines: 10.4 k · lean4export: 3.1.0 · Lean: 4.29.1 · 📄 Declaration · 🔗 Source

The declaration to check has type Nat and value

let x₃ := 0; x₃ + (let x₂ := 0; x₂ + (let x₁ := 0; x₁ + (x₃ + (x₂ + (x₁ + 0)))))

shown at n=3: n let bindings, each separated from the next by an addition, over an innermost sum that names every binding.

Substituting a binding into the body before checking it traverses O(n) nodes at each of the n bindings, for Θ(n²) in time and in allocated nodes. Recording the binding and reading it where the body names it costs O(1) per binding, for Θ(n).

The additions are what keep the bindings apart: a run of adjacent lets could be opened by a single substitution; not so here. Nat.add is the only application head, so no beta reduction is involved.

N=2000 in the Lean source.

Checker Result ⏱️ 🧠
mathgraph 👍 4 ms (÷232) 51.9 MB (÷6.1)
ind-models 👍 1.1 s (+4%) 352.4 MB (+12%)
official-nightly 👍 1.0 s (-1%) 318.7 MB (+1%)
evmlean 🚫 8.2 s 283.8 MB
nanoda 👍 631 ms (-38%) 306.2 MB (-3%)
mini 👍 1.3 s (+27%) 1.0 GB (×3.2)
lean4lean 👍 1.0 s (0%) 345.4 MB (+10%)
sokonanoda 👍 4 ms (÷232) 51.8 MB (÷6.1)
zignodamus 👍 4 ms (÷246) 9.5 MB (÷33)
nanoclo 👍 6 ms (÷177) 71.5 MB (÷4.4)
nanobruijn 👍 781 ms (-24%) 338.8 MB (+7%)
kiota 👍 697 ms (-32%) 838.6 MB (×2.7)
official 👍 1.0 s (0%) 315.3 MB (0%)
vow-lean-kernel 👍 31.6 s (×31) 525.2 MB (+67%)
rpylean 8 ms 18.1 MB
official-v4.28.0 👍 1.1 s (+9%) 321.4 MB (+2%)
still-nanoda 👍 634 ms (-38%) 306.2 MB (-3%)
nyaya 💥 4.3 s 718.1 MB
parse-only 👍 53 ms (÷19) 63.9 MB (÷4.9)