When does GC decide to collect generation 2?

2019-03-27 08:23发布

问题:

During the day I see a lot of gen 2 collections in our windows service.

When does GC decide to do full collection instead of collecting only Gen1 and Gen0 or only Gen0?

回答1:

Read http://msdn.microsoft.com/en-us/library/0xy59wtx.aspx and the linked articles for more information. In general, gen2 is collected "when necessary."

One thing that can cause excessive Gen2 collections is the large object heap (LOH). When the LOH gets filled, it will trigger a full collection. If your application allocates and frees lots of large objects (80K or larger), that could very well be your problem.

See CLR Inside Out: Large Object Heap Uncovered.

Also consider using the server garbage collector in your service. It will typically provide better performance (fewer collections). Add this to your app.config file:

<configuration
   <runtime>
      <gcServer enabled="true"/>
   </runtime>
</configuration> 


回答2:

Generally a colletion is triggered (under any generation) when 1 of the following is met

  • Allocation Exceeds the Threshold. I vaugly remember this being dynamic based on the current needs. Can anyone confirm/deny?
  • There is a Low Memory Situation
  • It is called via GC.Collect()

There may be another scenario I am missing, but generally that is it. The first one is what usually kicks off a collection, and conisdering it is (relativly) more expensive to collect G2 than G0 you see less of them.


To address the question in the comment:
Each generation has a threshold that when hit will trigger a collection. Gen0 could be 5mb, and will be triggered when that is filled. After GC runs, if you still have 5mb in there, I believe it will increase the limit. If it didn't than every allocation will trigger a collection, and you have an issue. Gen2 could be 20mb (note I am making up numbers here) and the same logic applies there.

For a textbook example, let's look at a simple scenario.

  1. New app allocated objects and all are put at Gen0 for a total of 3MB of data. (this is not always the case, but pretend it is)
  2. A GC hits, and 1 MB of that is moved to G1, the rest is cleaned up.
  3. G0 is now free, and G1 has 1MB in it.
  4. More objects are created, and more GC's happen. After a while G1 gets full, and some are moved to G2.
  5. Objects stay there until G2 is full, and then they are cleaned if not in use. If an object is still being referenced, it will stay in G2 until it can be cleaned.

A full GC is expensive, and I have seen days go by without one happening. Granted this was on a system with >64GB of ram available, and there was no need for it.