Test "perf/shift-cascade"
Expected: 👍 accept · Size: 256.3 KB · Lines: 5.1 k · lean4export: 3.1.0 · Lean: 4.29.1 · 📄 Declaration · 🔗 Source
Stress test for cascading substitution overhead in kernel let processing.
N nested let bindings inside a lambda, where each value references the
outer lambda parameter and the previous binding:
fun (a : Nat → Nat) => let f₁ := fun x => a x let f₂ := fun x => a (f₁ x) ... let fₙ := fun x => a (fₙ₋₁ x) fₙ 0
The kernel processes each let by substituting the value into the body.
Each value has a free bvar (references a), so substitution under inner
binders creates shifted copies. In a de Bruijn kernel with deferred shifts,
these Shift(val, offset) wrappers accumulate: step k must traverse
through O(k) wrappers from previous steps, giving O(N²) total work.
A locally-nameless kernel substitutes fvars that need no shifting, giving O(N) total.
N=1000 in the Lean source. Increase to stress further.
| Checker | Result | ⏱️ | 🧠 | |||
|---|---|---|---|---|---|---|
| mathgraph | 👍 | 3 ms | (÷17) | 46.4 MB | (-27%) | |
| ind-models | 👍 | 79 ms | (+70%) | 101.7 MB | (+59%) | |
| official-nightly | 👍 | 46 ms | (0%) | 66.2 MB | (+3%) | |
| evmlean | 👍 | 8.9 s | (×193) | 188.9 MB | (×3.0) | |
| nanoda | 👍 | 7 ms | (÷7.1) | 4.2 MB | (÷15) | |
| mini | 👍 | 1.8 s | (×40) | 70.1 MB | (+10%) | |
| lean4lean | 👍 | 49 ms | (+5%) | 96.0 MB | (+50%) | |
| sokonanoda | 👍 | 3 ms | (÷17) | 46.4 MB | (-27%) | |
| zignodamus | 👍 | 3 ms | (÷17) | 7.2 MB | (÷8.8) | |
| nanoclo | 👍 | 5 ms | (÷9.5) | 64.4 MB | (+1%) | |
| nanobruijn | 👍 | 164 ms | (×3.6) | 41.5 MB | (-35%) | |
| kiota | 👍 | 1.1 s | (×23) | 462.3 MB | (×7.2) | |
| official | 👍 | 46 ms | (0%) | 63.9 MB | (0%) | |
| vow-lean-kernel | 👍 | 317 ms | (×6.9) | 11.8 MB | (÷5.4) | |
| rpylean | 👍 | 7 ms | (÷6.9) | 18.2 MB | (÷3.5) | |
| official-v4.28.0 | 👍 | 55 ms | (+18%) | 75.1 MB | (+17%) | |
| still-nanoda | 👍 | 6 ms | (÷7.1) | 4.0 MB | (÷16) | |
| nyaya | 👍 | 32 ms | (-31%) | 15.0 MB | (÷4.3) | |
| parse-only | 👍 | 41 ms | (-10%) | 64.0 MB | (0%) |