Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does garbage collection run immediately after GC.Collect()? [closed]

The question is just for research purposes.

I've read many books about C# and this question always comes to my mind. What I understood that C# is managed code and all garbage collection occurs when CLR decides when to run garbage collection. Let's start.

Let's imagine that I have simple class Student:

public class Student
{
    public int IdStudent { get; set; }
    public string Name { get; set; }
    public string Surname { get; set; }
}
class Program
{
      static void Main(string[] args)
      {
This is row1:    Person person = new Person() {IdPerson=1, Name="Bill", SurName="Collins"};
This is row2:    System.GC.Collect();
This is row3:    string str="Hello World!";
    }        
}

Please, approve or reject my suppositions:

  1. Am I right that garbage collection is not run immediately at row2?
  2. GC.Collect() is just a request to make a garbage collection which DOES NOT RUN IMMEDIATELY at row2. This row maybe executed in x milliseconds/seconds. In my view, method System.GC.Collect(); just says to garbage collector that garbage collector should run garbage collection, but real garbage collection may occur in x milliseconds/seconds

  3. Only garbage collector knows when garbage collection will be run. And If there is free space in Generation 0, then garbage collection will not occur in the row2: row2: System.GC.Collect();

  4. It is not possible to run garbage collection immediately as we are programming in managed environment and only CLR decides when to run garbage collection. Garbage collection can be run in x milliseconds/seconds or garbage collection maybe not run cause there is enough space in generation 0 to create new objects after calling method GC.Collect(). What programmer can do is just ask CLR to run garbage collection by method GC.Collect().

Update:

I've read this msdn article about GC.Collect Method ().. However, it is unclear to me when real clearing of unreferenced objets is started. MSDN says:

GC.Collect Method () forces an immediate garbage collection of all generations.

However, in Remarks I've read this one:

Use this method to try to reclaim all memory that is inaccessible. It performs a blocking garbage collection of all generations.

  1. I am confused by this "Use this method to TRY" and I think that garbage collection may not occur cause CLR decides that there is enough space to create new objects. Am I right?
like image 424
StepUp Avatar asked Jan 25 '16 08:01

StepUp


People also ask

Does garbage collection happen automatically?

In Java, garbage collection happens automatically during the lifetime of a program. This eliminates the need to de-allocate memory and therefore avoids memory leaks. Java Garbage Collection is the process by which Java programs perform automatic memory management.

What does GC collect () do?

It performs a blocking garbage collection of all generations. All objects, regardless of how long they have been in memory, are considered for collection; however, objects that are referenced in managed code are not collected. Use this method to force the system to try to reclaim the maximum amount of available memory.

What triggers garbage collection?

When a JVM runs out of space in the storage heap and is unable to allocate any more objects (an allocation failure), a garbage collection is triggered. The Garbage Collector cleans up objects in the storage heap that are no longer being referenced by applications and frees some of the space.

Does System GC force garbage collection?

we can never force garbage collection. System. gc is only suggesting vm for garbage collection, however, really what time the mechanism runs, nobody knows, this is as stated by JSR specifications.


2 Answers

SHORT ANSWER

Calling GC.Collect() will do a complete garbage collection and wait for it to finish, but it will NOT wait for any pending finalizers to run.

LONG ANSWER

You're partially right in your suppositions because the GC for running finalizers runs in one or more background threads. (But see the footnote at the end of this answer.)

However, it is possible to wait for a complete GC to finish by calling GC.WaitForFullGCComplete() and GC.WaitForPendingFinalizers() after you have called GC.Collect():

GC.Collect();
GC.WaitForPendingFinalizers();
GC.WaitForFullGCComplete();

However, be aware that The thread on which finalizers are run is unspecified, so there is no guarantee that this method will terminate.

Note that you should not normally use the GC in this way; I assume you have a special case that you need to address, or you are doing this for research purposes.

The only valid case I've seen for this is when an application is closing, and you want to (try to) ensure that all finalizers have been run - because, for example, they will flush log files etc.

As noted above, this still doesn't guarantee that all finalizers have been run; it's just the best you can do.

In answer to your point (5):

The documentation for GC.Collect() states:

Forces an immediate garbage collection of all generations.

So this will force a GC.

The documentation also states:

Use this method to try to reclaim all memory that is inaccessible.

The use of the word "try" there merely means that even if a full GC is run, not all inaccessible memory will necessarily be reclaimed. There are several reasons that can occur, for example, a finalizer may block.

Footnote

.Net 4.5 allows you to specify whether GC.Collect() is blocking or not.

In fact, the documentation for GC.Collect() states that It performs a blocking garbage collection of all generations, which would appear to contradict my statements above. However, there seems to be some confusion as to whether this really is the case.

See for example this thread.

The answer is this: GC.Collect() will by default wait for all generations to be GCed, but it will NOT wait for pending finalizers, which are always executed in a separate thread.

Hence if you do not need to wait for finalizers, you ONLY need to call GC.Collect() and you do NOT need to wait for anything else.

like image 180
Matthew Watson Avatar answered Oct 19 '22 07:10

Matthew Watson


There are two GCs and from your code, I belive you want to know about Workstation GC. Which minimizes pauses by running concurrently during full collections? The Workstation GC uses the second processor to run the collection concurrently, minimizing delays while diminishing throughput. We should be only worried about GC behaviour if server GC is not doing its job properly. If you add GC.collect() in your code as per workstation GC, that may be useless on Server GC.

The server GC is designed for maximum throughput, and scales with very high performance. Memory fragmentation on servers is a much more severe problem than on workstations, making garbage collection an attractive proposition. In a uniprocessor scenario, both collectors work the same way: workstation mode, without concurrent collection

I am confused by this Use this method to TRY and I think that garbage collection may not occur cause CLR decides that there is enough space to create new objects. Am I right?

For workstaion GC, GC.Collect will start collecting as soon as possible, you can assume safely it collect immediately.

like image 26
Anil Avatar answered Oct 19 '22 07:10

Anil