Skip to content

[MicroPerf] Eliminate closure allocations in well-known-attribute queries - #20423

Merged
T-Gro merged 2 commits into
mainfrom
t-gro-attr-query-closures
Sep 9, 2026
Merged

T-Gro merged 2 commits into
mainfrom
t-gro-attr-query-closures

Conversation

@T-Gro

@T-Gro T-Gro commented Sep 2, 2026

Copy link
Copy Markdown
Member

Well-known-attribute queries partially applied computeEntityWellKnownFlags g / computeValWellKnownFlags g to non-inline caching methods, so each query heap-allocated an FSharpFunc even on a cache hit. The queries now test a function-free NeedsCompute bit and compute (on a miss only) with a fully-applied call; an inline Array.tryPick twin folds the remaining lambda.

Closure allocation eliminated — gc-verbose sampled, fsc self-compiling the 455-file FSharp.Compiler.Service (Release/net11):

closure site before after
tryFindILAttribByFlag@204 87.6 MB 0
EntityTryGetBoolAttribute@734 55.2 MB 0
ArgReprInfoHasWellKnownAttribute@716 31.0 MB 0
check result
closure classes in emitted FSharp.Compiler.Service.dll 3 on main → 0 here
FSharp.Compiler.Service.dll size −21,504 bytes
diff +63 / −73, 7 files
behaviour cached flag values identical; attribute/accessibility ComponentTests pass

@T-Gro
T-Gro requested a review from a team as a code owner September 2, 2026 10:33
@T-Gro T-Gro added Theme-Performance NO_RELEASE_NOTES Label for pull requests which signals, that user opted-out of providing release notes labels Sep 2, 2026
@T-Gro
T-Gro requested a review from abonie September 2, 2026 10:33
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

⚠️ Release notes required, but author opted out

Warning

Author opted out of release notes, check is disabled for this pull request.
cc @dotnet/fsharp-team-msft

@github-actions github-actions Bot added the AI-Tooling-Check-Bypassed Tooling check: non-fork PR, not diff-analyzed label Sep 2, 2026
Comment thread src/Compiler/TypedTree/TypedTreeOps.Attributes.fs Outdated
perf-bundle and others added 2 commits September 7, 2026 14:47
The well-known-attribute query helpers partially applied computeXxx g to
non-inline caching methods (CheckFlag / HasWellKnownAttribute(flag,compute)),
allocating a closure on every query even on cache hits. Replace that with a
two-phase form: test a function-free NeedsCompute bit, and on a miss classify
with a fully-applied computeXxx g attribs (a plain call, no closure), store,
then do function-free bit tests. Also add an inline Array.tryPick twin in
Internal.Utilities.Library that shadows FSharp.Core's at tryFindILAttribByFlag,
folding that lambda closure. Behavior is unchanged (per-entity/val caching
still lives in the flag bitfield). Removes the now-dead CheckFlag /
compute-overload methods.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Use an inline helper with an InlineIfLambda setter so Val and argument queries share cache initialization without reintroducing closure allocations.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@T-Gro
T-Gro force-pushed the t-gro-attr-query-closures branch from 9dcc9f3 to 8501fde Compare September 7, 2026 12:50
@T-Gro
T-Gro enabled auto-merge (squash) September 8, 2026 07:45
@github-project-automation github-project-automation Bot moved this from New to In Progress in F# Compiler and Tooling Sep 9, 2026
@T-Gro
T-Gro merged commit 2ef03e9 into main Sep 9, 2026
52 checks passed
bartelink pushed a commit to bartelink/fsharp that referenced this pull request Oct 7, 2026
…ries (dotnet#20423)

* Eliminate closure allocations in well-known-attribute queries

The well-known-attribute query helpers partially applied computeXxx g to
non-inline caching methods (CheckFlag / HasWellKnownAttribute(flag,compute)),
allocating a closure on every query even on cache hits. Replace that with a
two-phase form: test a function-free NeedsCompute bit, and on a miss classify
with a fully-applied computeXxx g attribs (a plain call, no closure), store,
then do function-free bit tests. Also add an inline Array.tryPick twin in
Internal.Utilities.Library that shadows FSharp.Core's at tryFindILAttribByFlag,
folding that lambda closure. Behavior is unchanged (per-entity/val caching
still lives in the flag bitfield). Removes the now-dead CheckFlag /
compute-overload methods.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Deduplicate well-known value attribute caching

Use an inline helper with an InlineIfLambda setter so Val and argument queries share cache initialization without reintroducing closure allocations.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: perf-bundle <perf@local>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI-Tooling-Check-Bypassed Tooling check: non-fork PR, not diff-analyzed NO_RELEASE_NOTES Label for pull requests which signals, that user opted-out of providing release notes Theme-Performance

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

3 participants