Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does setting an item null in a .NET List<T> make it available for Garbage Collection and is it a good idea?

Tags:

c#

.net

Suppose I have a large list where each item is processed once then never looked at again during a long operation:

List<T> items;
 // ... some stuff is done with the list then finally

 for(int i = 0; i < items.Count; i++)
 {
     SomeOperation(items[i]);
     //items[i] never used again at this point
     // say i do this:
     // items[i] = null;

 }

If I uncomment items[i] = null, will this unroot the object at index i and make it available for Garbage Collection?

Would it be more efficient, from a memory usage standpoint, to do this versus letting GC happen later when the entire list is unused down the road.

This is ignoring some problems like the code changing later and it turns out the items are used later and unexpected null wreck havoc.

like image 621
nlh3 Avatar asked Jan 06 '15 15:01

nlh3


People also ask

Is null eligible for garbage collection?

SO no, GC will never remove nulls from an array.

What does setting an object to null do?

If the reference is an instance variable, then setting it to null makes the object available for GC as long as there are no other references to it. However, if you set an instance variable to null, no other method in the class will be able to access that object using that variable.

What triggers garbage collection in C#?

Garbage collection occurs when one of the following conditions is true: The system has low physical memory. The memory that is used by allocated objects on the managed heap surpasses an acceptable threshold. This threshold is continuously adjusted as the process runs.

How does .NET framework manage garbage collection?

NET's garbage collector manages the allocation and release of memory for your application. Each time you create a new object, the common language runtime allocates memory for the object from the managed heap.


3 Answers

If the only root-accessible reference to that object is through that list, then yes, setting that reference to null will make that object eligible for garbage collection.

When a garbage collection eventually happens, if that object ends up being cleaned up while the list itself needs to stay around, then you will have decreased the memory footprint of your application by the size of that object.

Note that the memory allocated for the reference to the object in the list will still be there; it is only the memory for the object that it references that can be cleaned up.

As many others have mentioned, your usage of this data structure strongly indicates that you should not be using a List in the first place, but rather a Queue or another comparable data structure, as that would fit your usage much more effectively.

You also need to keep in mind that memory is cheap; people tend to have a lot of it. Unless you have many thousands of objects that would otherwise be kept alive for long periods of time, this is unlikely to be enough of an improvement for you to even notice it; you may not even be capable of measuring the difference. Using the correct data structure would give you all of those benefits, and more, and make the code dramatically simpler, and more readable/maintainable.

like image 182
Servy Avatar answered Oct 03 '22 01:10

Servy


Yes, if list has last reference to an object setting element to given index to null makes object eligible for GC.

It is not a good idea:

  • code will look strange. Possibly good comment why it is done can help.
  • there are likely better ways to express that behavior.

If you tried setting element to null and profiling shows measurable increase in performance/scalability/whatever you are looking for - consider rewriting code to use some other more appropriate construct that better express temporary nature of the list (maybe Queue, Stack or just IEnumrable with lazy evaluation)

When it may be beneficial (make sure to profile to prove):

  • list contains large managed objects like Bitmaps or MemoryStream. In this case GC have good chance to actually automatically run and clean up objects (assuming there are more allocations during iteration)
  • list contains small managed objects holding large un-managed objects (like globally allocated memory handles) - setting to null + proper Dispose + force GC may be needed to trigger early cleanup (GC will not detect un-managed memory pressure)
  • list is used as backing storage for some data structure like custom Stack, Queue or CircularBuffer as part of your own library - setting element to default(T) / null is a smart way to prevent your custom data structure to prolong lifetime of objects no longer used by your type.

Note that in case of implementing custom data type you likely must do that due to general contract of data type and not due to profiling - i.e. it is expected that Stack completely forgets about object after "Pop". The code should have appropriate comment next to internalBuffer[i]=null; - i.e. "avoid holding reference after object removed from Stack".

like image 40
Alexei Levenkov Avatar answered Oct 01 '22 01:10

Alexei Levenkov


As discussed elsewhere, setting to null should allow the object to be garbage collected.

You say in a comment

I considered using another data structure like a queue, but that did not seem natural in the context of the other code where as a list does.

You could always initialize a Queue from a list:

List<T> list = GetList<T>();

Queue<T> queue = new Queue<T>(list); // O(n)

list.Clear(); // to free up memory as per requirement
like image 30
dav_i Avatar answered Oct 05 '22 01:10

dav_i