Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Why doesn't CLR immediately release local objects that leave the scope? #102109

Closed
SolarianZ opened this issue May 11, 2024 · 11 comments
Closed

Why doesn't CLR immediately release local objects that leave the scope? #102109

SolarianZ opened this issue May 11, 2024 · 11 comments
Labels
area-GC-coreclr question Answer questions and provide assistance, not an issue with source code or documentation.

Comments

@SolarianZ
Copy link

Why doesn't CLR immediately release local objects that leave the scope?

In this example, object "temp" can be released immediately.

object[] Func()
{
    List<object> temp = new List<object>(100);
    // collect...
    object[] objs = temp.ToArray(); // The scope of 'temp' ends here
    return objs;
}
@dotnet-issue-labeler dotnet-issue-labeler bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label May 11, 2024
@dotnet-policy-service dotnet-policy-service bot added the untriaged New issue has not been triaged by the area owner label May 11, 2024
Copy link
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

@huoyaoyuan huoyaoyuan added area-GC-coreclr and removed area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI labels May 11, 2024
Copy link
Contributor

Tagging subscribers to this area: @dotnet/gc
See info in area-owners.md if you want to be subscribed.

@huoyaoyuan
Copy link
Member

Because the GC isn't working by releasing objects. It's working by not preserving objects.

To determine an object is out of scope is a complex task. The object pointed by the variable can be assigned elsewhere. See the discussions at #1661 #4584 #97292 etc.

@SolarianZ
Copy link
Author

Thank you. Also, do you have more information to share about this?

Because the GC isn't working by releasing objects. It's working by not preserving objects.

@huoyaoyuan
Copy link
Member

Also, do you have more information to share about this?

Because the GC isn't working by releasing objects. It's working by not preserving objects.

The CLR GC is mark-compact GC. Every time when GC occurs, it scans for alive objects that is reference somewhere. The space occupied by dead objects become "hole" in the memory. It also has the ability to move alive objects to other place to eliminate holes.

Holes aren't reusable immediately. The allocator (new) only operates on blank segments to achieve performance. Thus, it's not useful to clear one object in a segment. The GC operates in batch by nature.

@SolarianZ
Copy link
Author

Thus, it's not useful to clear one object in a segment.

I have learned about the GC process of the CLR from "CLR via C#." When posing this question, I have considered the issue of "hole". What if we inform the CLR to allocate objects to a dedicated memory region using specific keywords(similar to what was mentioned in #1661)? All objects in this region would be immediately erase on scope ends and not allowed to be promoted.

@huoyaoyuan
Copy link
Member

It is effectively ref struct. ref struct is "allocated" in another way by declaring instances in local variables, and subject to lifetime rules, not allowed to be stored to any "normal" objects that's potentially alive longer.

Since it's just a new concept and fundamentally incompatible with existing types, existing code can't simply benefit from it.

@jkotas jkotas added the question Answer questions and provide assistance, not an issue with source code or documentation. label May 11, 2024
@Clockwork-Muse
Copy link
Contributor

As a side note: part of the complexity of the analysis is that (looking only at this method), the compiler can't actually know that temp is collectible - it's possible that ToArray() places a reference to this in the returned array!
(Or more mundanely, that somebody did something like temp.Add(temp);)

You need ownership tracking to be able to solve for this type of thing.

@CodingMadness
Copy link

As a side note: part of the complexity of the analysis is that (looking only at this method), the compiler can't actually know that temp is collectible - it's possible that ToArray() places a reference to this in the returned array! (Or more mundanely, that somebody did something like temp.Add(temp);)

You need ownership tracking to be able to solve for this type of thing.

Not sure exactly how Rust does it exactly but can you make use of the "Burrow" concept here? Sort of using that model from Rust to keep track of dangling or valid references and hence deciding when and if to release them by the GC without promoting them to higher Gens.

@alexrp
Copy link
Contributor

alexrp commented Jun 21, 2024

In a word, no. Rust's borrow checker imposes restrictions that don't exist in C#, and also requires deep language/compiler support, so it is not really applicable in any useful sense.

@mangod9
Copy link
Member

mangod9 commented Jul 3, 2024

closing since the question looks to be answered

@mangod9 mangod9 closed this as completed Jul 3, 2024
@dotnet-policy-service dotnet-policy-service bot removed the untriaged New issue has not been triaged by the area owner label Jul 3, 2024
@github-actions github-actions bot locked and limited conversation to collaborators Aug 3, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-GC-coreclr question Answer questions and provide assistance, not an issue with source code or documentation.
Projects
None yet
Development

No branches or pull requests

7 participants