Conversation
… fixed point
`ExpGraph.combine` finds the coarsest bisimulation by partition refinement,
restarting from the one-class partition and re-splitting every node on each
pass. A pass distinguishes one more level of structure, so a graph that is a
chain of `n` distinct nodes needs `n` passes of O(n log n) work. `typ_hash`
canonicalizes on every call, and codegen names each generated
`@deserialize_go` / `@buffer_size` function by the hash of its type, so a type
nested `n` deep is hashed once per level -- making compilation cubic in the
nesting depth.
On an acyclic graph bisimilarity is just structural equality, which can be read
off bottom-up in a single pass: in topological order a node's class follows
from its label and its children's already-final classes. Take that path when
the graph has no cycle and keep the fixed point for recursive types, where it
is still needed (`type A = ?[A]` and `type B = [?B]` denote the same regular
tree without being structurally equal).
`test/bench/typtbl.mo` nests arrays up to 1024 deep:
depth before after
256 1.32s 0.76s
512 10.01s 0.55s
768 36.83s 0.97s
1024 94.53s 1.63s
and the benchmark as a whole goes from 2m16s to 2.5s. Type checking was never
implicated -- `moc --check` on that file takes 0.03s.
Output is unaffected: `wasm2wat` of `typtbl.mo` before and after differs only
in the embedded version string.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ggreif
commented
Sep 16, 2026
ggreif
commented
Sep 16, 2026
ggreif
commented
Sep 16, 2026
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contributor
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ggreif
commented
Sep 16, 2026
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ggreif
marked this pull request as ready for review
September 16, 2026 14:07
Contributor
Cursor AI review👍 APPROVE — looks safe to merge
VerdictDecision: APPROVE Generated for commit f5836dc |
ggreif
enabled auto-merge
September 16, 2026 14:50
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes the long-standing complaint that
test/bench/typtbl.motakes over twominutes to run.
Diagnosis
The type checker is not implicated:
moc --checkon that file takes 0.031s.All the time is codegen, and it is cubic in the nesting depth:
ExpGraph.combinefinds the coarsest bisimulation by partition refinement,restarting from the one-class partition and re-splitting every node on each
pass. A pass distinguishes one more level of structure, so a chain of
ndistinct nodes needs
npasses.typ_hashcanonicalizes on every call, andcodegen names each generated
@deserialize_go/@buffer_sizefunction by thehash of its type — so a type nested
ndeep is hashed once per level.Fix
On an acyclic graph bisimilarity is just structural equality, which can be read
off bottom-up in a single topological pass. Cyclic types keep the fixed point,
where it is genuinely needed:
type A = ?[A]andtype B = [?B]denote thesame regular tree without being structurally equal.
test/bench/typtbl.moas a whole: 2m16s → 2.5s.Verification
wasm2watoftyptbl.mobefore and after is 390,978lines each, differing only in the embedded version string — not one
instruction.
dune runtest mo_typespasses, including themonolist/polylistcasesthat exercise the cyclic path.
test/run(312 programs, cleaned before each run, quietmachine): 163.50s with the patch vs 164.49s without (real), 130.02s vs
131.42s (user) — a wash, within noise.
nix build .#common-tests .#gc-testspasses locally.🤖 Generated with Claude Code