Garbage collection on removal of root - c#

I have a binary tree implemented in c# with a method clear() which makes the root null, thus removing the reference to the root node in the heap. This makes the root node in the heap eligible for garbage collection.
But during a garbage collection cycle will only the root node be collected and then its two children will become eligible for garbage collection in the next cycle and taking as many cycles to remove the tree as the depth of the tree or will the whole tree in the heap be collected in one cycle?

The whole tree will be collected because the GC finds in one cycle ALL objects which cannot be reached. Because none of the nodes in your tree are reachable (from some live root), the entire set of nodes should be GCed.
This is an efficient way for the GC to work - but it's also a good way for it to deal with self-referential data structures such as a doubly-linked list (which would cause problems for any algorithm which didn't take "reachability from some reachable root" into account).

Actually that depends on how long your objects have been alive.
.NET uses an algorithm named 'mark & sweep', which is described here. The algorithm basically marks everything for removal, except the things that can be reached. Your objects will be removed in one iteration here.
However, naive mark & sweep will take a lot of time, since most "long-lived" objects will survive the GC. The more long-lived objects you have, the more time the GC will require to mark all objects. This is why .NET keeps track of how many GC cycles an object has survived. If it survives a couple of times, the next GC will skip the object. These are called 'generations' and are described on MSDN. Simply put, more times an object has survived a GC cycle, the less frequent it will be visited by the garbage collector for removal.
However, once your structure is at some point marked as 'not referenced' by the GC, the complete structure will be removed in one single pass.

Related

If I remove elements from a List - does this mean my RAM is also cleared/released via the garbagecollector or somehow?

In my program I add millions of records in a List in a loop, so as the program continues my RAM seems to grow too (I suspect because new and new elements are added to the list) - so if a timer tick event or just button push results in list.Clear(): will this immediately release my RAM? The ram seems to grow a lot to 500mb+ so with limited free amount on amazon instances this is an issue...thanx!
List have Clear() or Remove() methods to clear or Remove the Items within the List.
Force the Objects within the List which are not in use, to be cleared. Or Can assign null values to those Objects which are not in use, so that the Null Assigned Objects can Flag the GC that it is not in use and is ready to be Collected.
Assigning List Object to Null after the use, would also help GC to handle it well.
ie: myListVariable = null;
So that the memory can be cleared by the GC and can be freed from the unused Objects.
It's really not recommended, but you can force the garbage collector to run after you've cleared the list?
I found this link:
How to force garbage collector to run?
I'd look into implementing the iDisposable interface into your class. This would make it a managed resource and should automatically clear system resources when you're done with the data.
Good luck!

Will the garbage collector free this List when my method finishes running

Lets say I have something like:
public class Item
{
public string Code;
public List<string> Codes = new List<string>();
}
private void SomeMethod()
{
List<Item> Items = new List<Item>();
for (int i = 0; i < 10; i++)
{
Item NewItem = new Item();
NewItem.Code = "Something " + i.ToString();
NewItem.Codes.Add("Something " + i.ToString());
Items.Add(Item);
}
//Do something with Items
}
I am instantiating Item and not free'ing it because I need to have access to it in the list later on (rough example).
What I am wondering is when SomeMethod() has finished executing, will Items (and the contents of it - including the List<>) be de-referenced and allow the garbage collector to clean up the memory as and when it runs? Basically, will this section of code cause any memory leaks or should everything be de-referenced when SomeMethod() has finished processing.
My understanding is that when nothing holds a reference to an object it will be garbage collected so in my mind this code should be Ok but I just wanted to make sure I understand correctly.
EDIT:
If I was to add one of the objects Items is holding into another list that would still be in scope (a global list for example). What would happen?
Once your variable Items goes out of scope, the garbage collector will indeed dispose of it (and its contents, as your code is written) at its leisure.
The garbage collector will collect anything that is no longer reachable by code. Since you will no longer be able to reach your Items list or any of the Items contained within the list, then the garbage collector will collect them at some point. Your understanding of the garbage collector is correct.
Ok,
List<Item> Items
is declared in the scope of the method. So when the method ends, it goes out of scope and is the list is dereferenced.
The memory will be released at some point after that, when the Garbage Collecter sees fit.
As an aside, since Items is declared in a "local" scope I'd prefer to call it items.
all the variables in the method are in a stackframe and all these variable will be destoried along with the stackframe after the method was executed.
that is said after SomeMethod() executed, the variable Items will nolonger exists, thus new List() will be marked "can be collected".
the second question is that, there is a globle list variable hold the reference of one of the object that in the variable Items, then after the SomeMethod() executed, the List in the SomeMethod will be marked as "can be collected", and all the other object beside the item that was referenced by the globle list variable will also be makred as "can be collected"
the reason is, the list actually hold the reference that point to the exact object in the heap
So the shared object can not be collected due to the reason that it is referenced by the globleList
In order to keep things sane and keep its job, GC has to promise two things:
Garbage will be collected. This seems pretty obvious, but if the GC doesn't promise to clean up managed objects without you having to tell it to, it's rather useless.
ONLY garbage will be collected. You don't have to worry about the GC cleaning up objects that are still in play.
So, once Items goes out of scope (that is, once the function returns), it's no longer reachable by running code, so it's eligible for collection without you having to do anything. Since the items in the list are no longer reachable either (their only link was in the list), they're eligible too. If you returned a reference to an entry in the list, though, that object is still in play and can't be collected yet. GC will do the right thing.
In fact, GC almost always does the right thing. There are really only three major cases you have to worry about:
If you're buiding a container (like if you're making your own List workalike). Any objects that no longer "exist" in the container as far as the user is concerned, should generally be set to null so the GC doesn't see them as reachable through your collection and erroneously keep them alive. If you remove an item from the collection, for example, null out the reference or overwrite it with another.
With large (>~85KB?) objects. They'll typically stick around in memory til they crowd out everything else, at which point a full GC cycle runs. (Normally, only certain likely-to-be-discarded objects are checked during a cycle. Full collections check pretty much everything, which takes significantly longer but might free more memory.)
If you're using IDisposable objects or native/unmanaged resources. Some incompetents don't know how to implement IDisposable correctly. If you're dealing with a library created by such an incompetent, then you'll need to ensure that you Dispose stuff, or only ever use it within a using block, or things can get really weird. (If you only use the .net API, you're pretty safe. But disposing is still good manners.)
For pretty much all other occasions, GC just works. Trust it.

Garbage collection and references C#

I have a design and I am not sure if garbage collection will occur correctly.
I have some magic apples, and some are yummy some are bad.
I have a dictionary : BasketList = Dictionary <basketID,Basket>
(list of baskets).
Each Basket object has a single Apple in it and each Basket stores a reference to an objectAppleSeperation.AppleSeperation stores 2 dictionaries, YummyApples = <basketID,Apple> and BadApples = Dictionary<basketID,Apple>, so when I'm asked where an apple is I know.
An Apple object stores BasketsImIn = Dictionary<ID,Basket>, which points to the Basket and in Shops, and the Apple in Basket.
My question is, if I delete a basket from BasketList and make sure I delete the Apple from BadApples and/or YummyApples, will garbage collection happen properly, or will there be some messy references lying around?
You are right to be thinking carefully about this; having the various references has implications not just for garbage collection, but for your application's proper functioning.
However, as long as you are careful to remove all references you have set, and you don't have any other free-standing variables holding onto the reference, the garbage collector will do its work.
The GC is actually fairly sophisticated at collecting unreferenced objects. For example, it can collect two objects that reference each other, but have no other 'living' references in the application.
See http://msdn.microsoft.com/en-us/library/ee787088.aspx for fundamentals on garbage collection.
From the above link, when garbage collection happens...
The system has low physical memory.
The memory that is used by allocated objects on the managed heap surpasses an acceptable threshold. This means that a threshold of acceptable memory usage has been exceeded on the managed heap. This threshold is continuously adjusted as the process runs.
The GC.Collect method is called. In almost all cases, you do not have to call this method, because the garbage collector runs continuously. This method is primarily used for unique situations and testing.
If you are performing the clean-up properly, then you need not worry!

Does dequeue'ing an object remove the reference from the Queue object and allow for GC?

Some backgroud:
I am looking at the various collection objects available to me in the .NET framework and trying to make a decision on which one to use.
I have to go through each object in a collection, not necessarily enumerate through them, process, and remove it. I have to do this in memory and the dataset will be large (closing in on a gig). I need my memory footprint to reduce as quickly as possible.
Question:
Does dequeue'ing an object from the Queue collection free that reference in the queue so the garbage collector can do its job? (assuming no other reference to the dequeued object)
If you're talking about the built-in Queue<T> and Queue collections then yes, when an object is dequeued then the element in the backing array that previously held that object is set to default(T)/null, which should allow the object to be subsequently collected.
Behind the scenes, the Queue class maintain an internal circular array and two variables that serve as markers for the beginning and ending of the circular array: head and tail.
The Enqueue() method starts by determining if there is sufficient capacity for adding the new item to the queue. If so, it merely adds the element to the circular array at the tail index, and then "increments" tail using the modulus operator to ensure that tail does not exceed the internal array's length. If, however, there is insufficient space, the array is increased by a specified growth factor. This growth factor has a default value of 2.0, thereby doubling the internal array's size, but you can optionally specify this factor in the Queue class's constructor.
The `Dequeue()` method returns the current element from the head index.
It also sets the head index element to null and "increments" head.
So the 'dequeued' object is set to
null and later on GCed as needed, although non-deterministic; the times when GC runs can vary.
Assuming you hold no additional references to those objects, removing them will mark them for GC, though there is no guarantee when the collection will actually happen. If you have additional references, the objects will be retained in memory until those references are released.

Clearing a double-linked list

I have a double linked list (queue) I have made on my own.
I am wondering, to clear the linked list, is it enough to simply remove the head and tail references?
E.g
public void Clear()
{
Head = null;
Tail = null;
}
I am imaging a domino effect, but I am having a hard time testing it.
It WILL make the whole object appear empty atleast. All data requests (such as peek, dequeue etc.) returns null.
You can also easily Enqueue some new objects.
Purely functional it seems to be working.
But I'd really like to know if I am doing it the right way.
The short answer is yes, garbage collection will clear out all the linked list nodes, provided that nothing external holds a reference to them.
Easiest way to test is to add a finalizer to your linked list node object that outputs some logging. Note that you can't be sure when the garbage collector runs (without forcing it, via GC.Collect()) so you won't see the finalizer called as soon as you call you Clear() method.
The "domino effect" is not going to happen, though; it doesn't matter if references are held to an object, rather than references can be traced back to the stack or a static object. So if several objects refer to each other, but nothing refers to them, then they'll all be garbage collected simultaneously.
Unless the objects in the collection needs to be disposed of, and it is the responsibility of the collection to do that, then your method is probably the best way.
Since there is no root to the object (no live references), garbage collection can pick it up and remove it.
I am imaging a domino effect
This isn't how the GC works.
The GC first marks everything "dead", then starting at the root objects it traverses all objects referenced by them, marking each one as "alive".
Since your list is no longer reference by any root objects (or children of) it will be left marked "dead".
The second pass then frees the "dead" objects.
I doubt that you can assume in a finalizer that any objects either side in the list have not been collected first, ie it will be in the GC's own order not the order of the list.
A bit more detail here:-
http://msdn.microsoft.com/en-us/magazine/bb985010.aspx

Categories

Resources