Skip to content

perf(compile): fix O(N^2) map-lookup compiler hang (audit-resolve regression) + attest sha fix#14

Merged
zemo-g merged 2 commits into
masterfrom
land/compiler-perf-fix
Jun 15, 2026
Merged

perf(compile): fix O(N^2) map-lookup compiler hang (audit-resolve regression) + attest sha fix#14
zemo-g merged 2 commits into
masterfrom
land/compiler-perf-fix

Conversation

@zemo-g

@zemo-g zemo-g commented Jun 15, 2026

Copy link
Copy Markdown
Owner

Lands the compiler perf fix on master, rebased onto current master (incl. B1/B2 PR #12).

The hang: audit-resolve's float-dataflow passes search the arity/marker maps millions of times through efind/afind, whose length env == 0 empty-check is O(N) per step (_rail_length walks the list) -> O(N^2) lookups. Any json-importing TLS program (attest.rail) took >30 min to compile. Fixed to == [] (O(1)) + skip a redundant float-path fixpoint when the HOF seed already converged. Both byte-identical.

Verified on this branch (bootstrapped from master's B1-capable seed, since compile.rail uses char_from_int 0):

  • attest.rail: >30min -> 12s
  • 177/177 tests, 0 fail
  • 2-pass self-host fixed point byte-identical (rail_native reseeded, id rail_self)

Also includes the attest sha fix (read_file_bytes_open) so verify.rail/attest.rail digest binaries correctly.

🤖 Generated with Claude Code

zemo-g and others added 2 commits June 15, 2026 16:26
…e_bytes builtin

sha256_hex_file read file bytes through the bare `read_file_bytes` builtin,
which returns a string-like buffer whose arr_len reads its first content bytes
as the length (0x6161 for "aa"; garbage-negative for bytes >=128). arr_len +
sha_final_block then overran and segfaulted on any non-ASCII file -- including
the physicify coinage. Read via read_file_bytes_open (stdlib/file.rail), which
returns a real int array; file_size_bytes uses read_file_size. verify.rail and
attest.rail both fixed; they now mint+verify the coinage clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Regression from the audit-resolve merge: the float-dataflow passes
(collect_argf_unified / collect_hofpos) search the arity/marker maps millions
of times, and two compounding costs made any json-importing TLS program --
e.g. tools/attest/attest.rail -- take >30 min to compile, a de-facto hang.

1. efind/afind/rmap_set/rmap_eq used `length env == 0` as their empty check.
   _rail_length walks the whole list, so that test is O(N) PER recursion step,
   making each map lookup O(N^2). Switched to `== []` (O(1)). Identical return
   values -> identical codegen.
2. collect_argf_unified always ran a second collect_argf_fix, even when the
   higher-order-float seed had already converged (hof2 == hof1). Return argf1
   directly there -- a pure re-derivation. Only a float FOLD needs the 2nd pass.

attest.rail >30min -> 12s; self-compile faster; 177/177 tests; 2-pass self-host
fixed point byte-identical (rail_native reseeded). Bootstrapped from master's
B1-capable seed since compile.rail's own source uses char_from_int 0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@zemo-g zemo-g merged commit 7468d15 into master Jun 15, 2026
3 checks passed
@zemo-g zemo-g deleted the land/compiler-perf-fix branch June 15, 2026 21:27
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