Uh oh!
There was an error while loading. Please reload this page.
Avoid per-instance lock object in InterruptibleLazy and DelayInitArrayMap - #20088
Conversation
25074ee to
bdb5b04Comparemajocha
commented
Jul 28, 2026
The way |
auduchinok
commented
Jul 28, 2026
Thanks for the suggestion! The problem is it still keeps the memory for that field, and for many thousands of types it's becoming a bit too much. |
auduchinok
commented
Jul 28, 2026
Here's an interesting discovery about how this PR overlaps with #20090:
|
T-Gro
left a comment
There was a problem hiding this comment.
🤖 This review was generated by AI (@expert-reviewer agent). Findings may contain inaccuracies — please verify independently.
The change is mechanically correct: the private constructor makes InterruptibleLazy effectively sealed, and both DelayInitArrayMap subclasses (ILMethodDefs, ILTypeDefs) are sealed and never lock on this, so there is no internal lock collision. GetDictionary also calls GetArray() before entering its own monitor, so there is no nested self-lock. The memory win is real and worthwhile. The only caveat is the general lock-on-this concern already noted in the PR description — see the inline comment.
Uh oh!
There was an error while loading. Please reload this page.
bdb5b04 to
a040e8aCompare❗ Release notes requiredYou can open this PR in browser to add release notes: open in github.dev
|
T-Gro
commented
Aug 12, 2026
It would really great if we could annotate a type that locks itself, and then have a scanner making sure such type is never the subject to I am more afraid of future changes regressing this, I think a one-off analysis for current snapshot is fine here. |
Head branch was pushed to by a user without write access
…yMap Both types allocated a dedicated `syncObj = obj()` for their one-time initialisation. These instances are internal and never locked externally, and there are enough of them (one per lazy IL member, per ILTypeDefs / ILMethodDefs, etc.) that the extra bare System.Object adds up to tens of MB on a large project. Lock on `this` instead and drop the field. Measured on a single-file FCS check against a project with ~486 references: bare System.Object instances dropped from ~1,000,000 to ~29,000 (~-22 MB). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
0e4e1f9 to
9416709CompareUh oh!
There was an error while loading. Please reload this page.
I've been measuring memory allocations on some my changes and found out that these sync objects retail a lot of memory due to usages like in
ImportILTypeDef. This is a debatable change: it makes things more dangerous (an issue could be if someone locks on the lazy itself) but at the same it's an implementation detail inside the compiler which is fairly advanced, so I hope that it can be used responsibly.