I'm having a trouble to understand what is the difference between WaitForFullGCComplete
and WaitForPendingFinalizers + collect
.
I already know that when a new object is created (which has a finalizer ) — A reference to that object is created in the finalization queue
.
Now - when a GC .collect
occurs and finds that the object should be collected , the reference from the finalization queue
moves to the f-reachable queue
.
These references in the queue are considered as a root
. Now — a special thread awakes from sleep at the f-reachable queue
and run each object's finalize
method .
Notice this is done AFTER the collect
phase. So only the next time we run GC.collect
the object would be truly gone.
If we want to wait until the f-reachable queue's
thread is done with all the finalize
methods - we should call : WaitForPendingFinalizers
.
And now if we want full collect , then we should run GC.collect again!.
If so - it seems that a full GC can be made by :
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true);
GC.WaitForPendingFinalizers();
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true);
So why would I need GC.WaitForFullGCComplete()
?
The docs says :
Returns the status of a registered notification for determining whether a full, blocking garbage collection by the common language runtime has completed.
Question
I don't understand : I already know when Gc has completed and it is at that point :
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true);
GC.WaitForPendingFinalizers();
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true);
//HERE <--
So when should I use that method as opposed to my code?
NB
(I saw it's usages here and here )
but their usage is not complete because - Not to mention that there is another method which should must be called in pairs :
From CLR via C# 4:
Note that you should always call the
WaitForFullGCApproach
andWaitForFullGCComplete
methods in pairs because the CLR handles them as pairs internally.
Suspends the current thread until the thread that is processing the queue of finalizers has emptied that queue. public: static void WaitForPendingFinalizers();
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.
Unless I misunderstood, both the usages in the link you've pointed out is wrong. As you quoted from CLR via C#, both WaitForFullGCApproach
and WaitForFullGCComplete
should be used in pairs.
WaitForFullGCComplete
is very different than Collect + WaitForPendingFinalizers
. Its usage is completely different.
Lets say you're writing a high performance, low latency server application which handles several thousands of requests per second. Obviously the server will allocate considerable amount of memory which can trigger a full gc(blocking!) which is a bad news for us.
Yes full gc will take a while to complete, till then you can't process the requests from clients (as your threads will be suspended). It isn't desirable for a high performance application to tolerate a full gc at peak hours.
In such case, if you want to redirect the further requests to some other server which can handle them, you'd use GC.RegisterForFullGCNotification
, GC.WaitForFullGCApproach
and GC.WaitForFullGCComplete
methods respectively.
WaitForFullGCApproach
will block till the GC decides to do a full gc, it is a notification for you to proactively redirect the requests or take some action.
Then WaitForFullGCComplete
will block till the full gc is completed. It is a notification for you to start processing the requests again.
GC.RegisterForFullGCNotification docs provides a good example and explains it better.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With