Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Doubts about .NET Garbage Collector

I've read some docs about the .NET Garbage Collector but i still have some doubts (examples in C#):

1)Does GC.Collect() call a partial or a full collection? 2)Does a partial collection block the execution of the "victim" application? If yes.. then i suppose this is a very "light" things to do since i'm running a game server that uses 2-3GB of memory and i "never" have execution stops (or i can't see them..). 3)I've read about GC roots but still can't understand how exactly they works. Suppose that this is the code (C#):

MyClass1:

[...] 
public List<MyClass2> classList = new List<MyClass2>(); 
[...]

Main:

main()
    {
     MyClass1 a = new MyClass1();
     MyClass2 b = new MyClass2();
     a.classList.Add(b);

     b = null;

     DoSomeLongWork();
    }

Will b ever be eligible to be garbage collected(before the DoSomeLongWork finishes)? The reference to b that classList contains, can it be considered a root? Or a root is only the first reference to the instance? (i mean, b is the root reference because the instantiation happens there).

like image 935
Smjert Avatar asked Feb 03 '23 05:02

Smjert


2 Answers

  1. There are a couple of overloads for GC.Collect. The one without any parameters does a full collect. But keep in mind that it is rarely a good idea to call GC explicitly.

  2. Garbage collections occurs within a managed application. The GC may have to suspend all managed threads in that process in order to compact the heap. It doesn't affect other processes on the system if that is what you're asking. For most applications it is usually not an issue, but you may experience performance related problems due to frequent collects. There are a couple of relevant performance counters (% time in GC, etc.) that you can use to monitor how the GC is performing.

  3. Think of a root as a valid reference. In your example the instance of MyClass2 will not be collected if there are still references to it. I.e. if the instance pointed to by a is still rooted so will your instance of MyClass2. Also, keep in mind that GC is much more aggressive in release mode builds than debug builds.

like image 92
Brian Rasmussen Avatar answered Feb 07 '23 11:02

Brian Rasmussen


  1. GC.Collect() does a full collection. That's why it's not a good idea to call it yourself, as it can prematurely promote objects up a generation

  2. AFAIK, not really. The GC blocks for so little time as to be inconsequential.

  3. A stack GC root is an object that is currently being referenced by a method on the stack. Note that the behaviour is different between debug and release builds; on debug builds all variables in a method are kept alive until the method returns (so you can see their value in the debug window). On release builds the CLR keeps track of where method variables are used and the GC can remove objects that are referenced by the currently executing method but aren't used in the section of the method that is still to execute.

So, in your example, both a and b are not referenced again after the DoSomeLongWork() call, so in release builds, during that method execution they would both be eligible for collection. In debug builds they would hang around until the main() method returns.

like image 41
thecoop Avatar answered Feb 07 '23 12:02

thecoop