Skip to content

[MicroPerf] Inline the free-variable typar foldBacks - #9

Closed
T-Gro wants to merge 1 commit into
t-gro-foldhierarchy-loop-lift-spikefrom
t-gro-freevars-inline-foldback
Closed

[MicroPerf] Inline the free-variable typar foldBacks#9
T-Gro wants to merge 1 commit into
t-gro-foldhierarchy-loop-lift-spikefrom
t-gro-freevars-inline-foldback

Conversation

@T-Gro

@T-Gro T-Gro commented Aug 27, 2026

Copy link
Copy Markdown
Owner

Stacked on dotnet#20373 — depends on its ListInline module. Base is this PR's branch on the fork (a dotnet/fsharp PR can't use a fork branch as base); it retargets to main once dotnet#20373 merges.

Free-variable computation is one of the hottest compiler traversals. accFreeInTyparConstraints and accFreeInTypars fold the top-level accFreeInTyparConstraint / accFreeTyparRef over a typar's constraint and typar lists — usually tiny or empty. Passed to List.foldBack, each call allocated a partial-application closure; since foldBack builds no result list, that closure is the entire allocation. ListInline.foldBack inlines the folder (InlineIfLambda) and the top-level partial application fuses, so nothing is allocated.

Closures eliminated (dotnet-trace gc-verbose, 6 self-compiles of a 120-file corpus):

closure before after
accFreeInTyparConstraint opts (foldBack) 147.8 MB 0
accFreeTyparRef opts (foldBack) 238.8 MB 0

Fold order is unchanged, so free-variable results are identical; compiler output is byte-identical under --deterministic+ (SHA-256 match vs base), and tests pass.

accFreeInTyparConstraints and accFreeInTypars fold accFreeInTyparConstraint /
accFreeTyparRef over a typar's constraint and typar lists during
free-variable computation, one of the hottest traversals in the compiler.
Passing those top-level functions to List.foldBack allocated a partial-
application closure per call, over typically tiny (often empty) lists where
the closure is the entire cost.

Switch both folds to ListInline.foldBack (added in the parent change), whose
InlineIfLambda folder inlines the top-level partial application, so no closure
is allocated. Fold order is unchanged; compiler output is byte-identical under
--deterministic+.

Measured (dotnet-trace gc-verbose, 6 self-compiles of a 120-file corpus):
accFreeInTyparConstraints closure 147.8 MB -> 0, accFreeTyparRef closure
238.8 MB -> 0.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c6610fae-a96e-4421-a920-e73de4fc94dc
@T-Gro
T-Gro marked this pull request as draft August 27, 2026 12:52
@T-Gro

T-Gro commented Aug 27, 2026

Copy link
Copy Markdown
Owner Author

Superseded by dotnet#20385 (proper same-repo stacked PR).

@T-Gro T-Gro closed this Aug 27, 2026
@T-Gro
T-Gro deleted the t-gro-freevars-inline-foldback branch August 27, 2026 12:59
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