Skip to content

perf(parse): a name finds its binder through an index, not a scan of every local - #2064

Open
nicolas-abril wants to merge 4 commits into
bendlang:mainfrom
nicolas-abril:perf/parse-var-index
Open

nicolas-abril wants to merge 4 commits into
bendlang:mainfrom
nicolas-abril:perf/parse-var-index

Conversation

@nicolas-abril

@nicolas-abril nicolas-abril commented Nov 5, 2026 •

Copy link
Copy Markdown
Collaborator

This PR edits bend2/bend.ts, which AGENTS.md marks as human-written. It was opened at Nicolas's request, as a proposal for the file's owner to review, rewrite or close.

The parser part of #2046. parse_var looked up a name by walking the scope stack stk from the newest binder down. Every use of an outer variable passed all the locals bound after it, and every global name (Unit, U32.add, …), which is never on the stack, passed all of them. n locals and n uses cost O(n²).

Parse now also keeps idx: each name's binders on stk, newest last. parse_push adds to both (parse_open and the rewrite binder's hidden _ go through it), parse_close pops both back to the mark, and parse_var reads the newest binder of its name directly. stk and its length marks stay as they were. The parser has no try/catch backtracking: every binder it opens is closed by parse_close before its scope's mark is reused, so idx always matches stk.

The conversion part of #2046 (term_higher's list_get) and its match-lowering part (in #2062) are not in this PR.

Load times (in-process book_load, best of 12)

program main this PR
2000 locals, then 2000 uses of a parameter bound before them (#2046's family) 36–37 ms 14 ms
2000 locals, then 2000 uses of a global constructor 13 ms 2.6 ms

On the checker benches the scope lookup (parse_var, parse_open, parse_close) falls from about 8.4 ms to 6.4 ms of parse time per run (CPU profile, 9 runs over generics_3200, defs_12800 and proofs_3200): their defs bind few locals, so the gain there is small.

Checks

  • Every .bend file under tests/ (1851 files) prints the same output with --check-only as on main, error messages included.
  • bend.ts 45508 → 45593 ttok (cap 48000).
  • Gates (_run.ts): repo 56/56, ping 83/83, perf 122/124 (the same cluster cells main fails today: merkle and nbody, compile and GPU time). Test gave 1830/1838 under _run, failing the io/gfx tests that stale /tmp/bend_io_* files on some cluster nodes break, and 1838/1838 in a separate run of the test gate.

🤖 Generated with Claude Code

nicolas-abril and others added 4 commits November 5, 2026 19:28
…every local

Parse keeps idx, each name's binders on stk, newest last. parse_push adds
to both, parse_close pops both back to the mark, and parse_var reads the
newest binder of its name directly instead of walking stk (bendlang#2046).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ads its last

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…sses 4096 names

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant