As I understand, garbage collector in c# will put all objects of a class into finalization queue, as soon as I implement destructor of the class. When I was reading documentation for GC.Suppresfinalize, it mentions that object header already has a bit set for calling finalize.
I am wondering that why the implementers of GC had to put all objects in a queue, and delay the freeup of memory by 1-2 cycles. Could not they just look at the bit flag while releasing memory, then call finalize of the object and then release memory?
No doubt I am an idiot and I not able to understand the working of GC. I am posing this question just to improve my understanding or fill the missing gap in my knowledge
EDIT : If the bit flag is for suppressfinalize, GC implementers could have added another flag in object header for this purpose, no?
So it can run in a different thread and thus keep from blocking the main GC thread.
You can learn a lot about the GC from this MSDN article.
There is a great explanation here
What are the Finalizer Queue and Control+ThreadMethodEntry?
Essentially the reasoning is that it may not always be ideal for the GC to have to wait on finalizer code to execute, so queuing finalizers allows finalization to be deferred until a time when it's more convenient.
It's desirable for garbage collection pauses to be as short as possible. To that end, running finalizers is usually deferred to a later time, when the frantic work of garbage collection is done. It is instead done in the background on a separate thread.
@Jason: this is true for the f-reachable queue. But IMHO it does not explain why there is the finalization-queue itself.
My guess is that the finalization-queue is there to add another information that helps the GC to distinguish between all the possible states of an object life-cycle.
The finalization flag in the object's header says "the object needs to be finalized" or "the object does not need to be finalized" but it does not say if the finalization has already occurred.
But to be honest I don't grasp why it's needed in the current finalization process implementation.
Indeed, here is the naive workflow I imagine possible without the finalization-queue:
So seems like in these scenarios there is no need for a finalization-queue, only the finalization flag is useful.
One possible reason would be that from a conceptual point of view there might be a rule like: "an object is collected if and only if it is not referenced from any root". So not having a finalization queue, and basing the decision to collect an object on the object state itself, checking the finalization flag, is not compatible with this rule.
But really I don't think the GC implementation is based on the dogmatic application of such theoretical rules but only on pragmatic choices; so it's obvious I'm missing some key scenarios where the GC needs the finalization queue to know what to do when collecting an object, but which ones?
The garbage-collector does not identify and examine garbage, except perhaps when processing the Large Object Heap. Instead, its behavior is like a that of a bowling-alley pinsetter removing deadwood between throws: the pinsetter grabs all the pins that are still standing, lifts them off the surface of the lane, and then runs the sweeper bar across the lane without regard for how many pins are on that surface. Sweeping out memory wholesale is much faster than identifying individual objects to be deleted. If 1% of objects have finalizers (the real number's probably even less), then it would be necessary to examine 100 object headers to find each finalizable object. Having a separate list of objects which have finalizers makes it unnecessary for the GC to even look at any garbage objects that don't.
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