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

岁酱吖の 提交于 2021-02-08 14:10:39

问题


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?

回答1:


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.




回答2:


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.



来源:https://stackoverflow.com/questions/34988198/does-garbage-collection-run-immediately-after-gc-collect

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!