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.
SO no, GC will never remove nulls from an array.
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.
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.
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.
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.
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:
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):
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".
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
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