Skip to content

Typechecker performance improvements - #521

Merged
rodrigogribeiro merged 4 commits into
mainfrom
typechecker-performance-tests
Jul 6, 2026
Merged

Typechecker performance improvements#521
rodrigogribeiro merged 4 commits into
mainfrom
typechecker-performance-tests

Conversation

@rodrigogribeiro

@rodrigogribeiro rodrigogribeiro commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator

This PR makes some changes on type inference to improve performance.

  • Single type-inference pass: merged the two full inference passes into one.
  • SYB span-stopping: A lot of typing time is spent by SYB traversals. The improvement is to make them not to check the AST Span information using new combinators in Traversal.hs
  • Subst as Data.Map: apply is now O(log n) instead of a linear association-list scan.
  • ordNub in fv/mv/bv: replaced O(n^2) Data.List.union accumulation.
  • Minor optimizations: removed dead nameSupply mutation in freshInst; askInstEnv
    alpha-renames only the queried class's instances, not the whole table.

Times in seconds (minimum of several warm runs on my machine). main is the original
two-pass baseline; optimized is this branch. tc = "Typecheck modules" phase; wall = total
compile time.

Program tc: main tc: optimized tc speed-up wall: main wall: optimized wall speed-up
storage 4.16 0.74 5.62x 5.21 1.04 5.00x
generic_sum 6.01 1.01 5.95x 7.43 1.39 5.33x
weth9 4.86 0.86 5.65x 6.09 1.22 5.00x
forloops 4.53 0.82 5.52x 5.68 1.16 4.88x
miniERC20 5.30 0.97 5.46x 6.50 1.30 5.00x

~5.6x faster type checking, ~5.0x faster total compile. Full unit suite (793 tests) went from
~100 s to 23.8 s; all 793 tests + 22 contest suites still pass.

@rodrigogribeiro
rodrigogribeiro requested review from Y-Nak and mbenke July 4, 2026 22:26

@mbenke mbenke left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! One question: it seems that noDesugarOpt is now not used in code, is it still needed in tests?

@Y-Nak Y-Nak left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@rodrigogribeiro
rodrigogribeiro merged commit ac6f895 into main Jul 6, 2026
4 checks passed
mbenke added a commit that referenced this pull request Jul 8, 2026
Brings in main's typechecker performance work (PR #521) on top of the
earlier main merge:

  * The double typecheck is gone: modules are inferred once, and the
    lambda/expected-type reconciliation the retired no-desugar pass used
    to provide is now folded into tcExpWithExpected' (TcStmt). The
    CheckedModule record loses its checkedModuleNoDesugar field and
    Options loses noDesugarOpt.
  * Assorted TcSubst/TcUnify/TcMonad/TcResolution speedups and a new
    Syntax/Traversal module.

Auto-merged cleanly; one hand-fix was required, folded in here:

  * TcCacheSerialize.fromCachedModule constructs a CheckedModule and set
    the now-removed checkedModuleNoDesugar field to an error thunk. With
    the field gone the record no longer compiles, so the line is dropped
    (only checkedModuleInput remains an unread thunk). The serialized
    cache format is unaffected: that field was never persisted.

Verified: native -Werror build clean; 811 unit tests pass (including the
typecheck-cache dump/load round-trip); optimised web/build.sh --release
green with a regenerated std-cache.bin.

Assisted-By: Claude Opus 4.8 <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.

3 participants