Skip to content

IL: reuse the cached ILTypeRef in ILTypeInfo.FromType - #20255

Open
auduchinok wants to merge 3 commits into
dotnet:mainfrom
auduchinok:il-tcref-mkref
Open

IL: reuse the cached ILTypeRef in ILTypeInfo.FromType#20255
auduchinok wants to merge 3 commits into
dotnet:mainfrom
auduchinok:il-tcref-mkref

Conversation

@auduchinok

Copy link
Copy Markdown
Member

ILTypeInfo.FromType built its ILTypeRef with mkRefForNestedILTypeDef scoref (enc, tdef) on every
call. For a TILObjectRepr entity, Entity.CompiledRepresentation already caches the result of that
exact expression
(TypedTree.fs), reachable as tcref.CompiledRepresentationForNamedType.

FromType is called once per MethInfoMethInfo.CreateILMeth calls it for every method of a type —
so the uncached path produced one duplicate ILTypeRef per method info, each re-deriving the enclosing
name list and re-computing the hash. This takes the cached one instead, in both the tuple and the plain
isILAppTy branch.

In a heap snapshot of ParseAndCheckProject over a 57-file project with 489 references, ILTypeRef
went from 150,928 live objects (8.06 MB) to 53,262 (2.84 MB)
— 98,398 of them were duplicates held
one-per-ILTypeInfo.

Project Before (MB) After (MB) Diff
consoleapp 33.84 33.84 −0.00 (−0.01%)
Fantomas.Core 109.37 109.28 −0.09 (−0.08%)
Fantomas.Core.Tests 141.89 141.55 −0.34 (−0.24%)
Fantomas.Benchmarks 64.81 64.79 −0.02 (−0.04%)
FSharp.Common 297.61 292.54 −5.07 (−1.70%)
fcs 1271.39 1264.63 −6.76 (−0.53%)

For a TILObjectRepr entity, Entity.CompiledRepresentation already caches
exactly 'mkRefForNestedILTypeDef scoref (enc, tdef)'. Take the ILTypeRef
from there instead of rebuilding an equal one - and its enclosing-name
list, and its hash - on every ILTypeInfo.FromType call.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@auduchinok
auduchinok requested a review from a team as a code owner August 13, 2026 11:01
@auduchinok auduchinok changed the title Reuse the cached ILTypeRef in ILTypeInfo.FromType IL: Reuse the cached ILTypeRef in ILTypeInfo.FromType Aug 13, 2026
@auduchinok auduchinok changed the title IL: Reuse the cached ILTypeRef in ILTypeInfo.FromType IL: reuse the cached ILTypeRef in ILTypeInfo.FromType Aug 13, 2026
@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

❗ Release notes required

You can open this PR in browser to add release notes: open in github.dev


✅ Found changes and release notes in following paths:

Change path Release notes path Description
`src/Compiler` docs/release-notes/.FSharp.Compiler.Service/11.0.100.md

@github-actions github-actions Bot added the AI-Tooling-Check-Scanned-Clean Tooling check: diff analyzed, no interesting infrastructure files label Aug 13, 2026

@T-Gro T-Gro 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.

Nice, surgical memory win — LGTM. ✅

I traced the equivalence to be sure the cached ref is identical, not just similar:

  • Both branches are gated by isILAppTy/ILTyconInfo, which require IsILTycon, i.e. TypeReprInfo = TILObjectRepr. So the entity is always a TILObjectRepr.
  • For exactly that shape, Entity.CompiledRepresentation (TypedTree.fs) computes mkRefForNestedILTypeDef ilScopeRef (ilEnclosingTypeDefs, ilTypeDef) — the same expression FromType was re-running with scoref (enc, tdef) — and CompiledRepresentationForNamedType returns that ILAsmNamed tref. Same value, now shared.
  • The one thing that could have diverged is that CompiledRepresentation consults ExceptionInfo before TypeReprInfo, but TExnAbbrevRepr/TExnAsmRepr only arise for F# exception entities, which are never TILObjectRepr and so never reach FromType. No behavior change.

Since ILTypeRef equality/hash is structural, collapsing the ~98k per-ILTypeInfo duplicates into the shared cached instance is pure upside — the heap numbers back it up nicely, and FromType runs once per MethInfo so this was a real hot allocator.

Verified locally: FSharp.Compiler.Service builds clean for net11.0 and netstandard2.0 (only the pre-existing FS3261 in XmlDocInheritance.fs).

Tiny non-blocking nit: the note landed under ### Added — a memory optimization reads more like ### Improved, but not worth a spin.

@github-project-automation github-project-automation Bot moved this from New to In Progress in F# Compiler and Tooling Aug 13, 2026
@T-Gro T-Gro added the AI-reviewed PR reviewed by AI review council label Aug 13, 2026
@T-Gro
T-Gro self-requested a review August 13, 2026 16:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI-reviewed PR reviewed by AI review council AI-Tooling-Check-Scanned-Clean Tooling check: diff analyzed, no interesting infrastructure files

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

2 participants