- Home /
If you destroy a List of Class objects...
Sorry for another lame-ass Unityscript question. (Where's the "idiot Unityscript questions" section of the forum??)
If you have a Unityscript struct,
class Concepts extends System.ValueType
{ }
and then you do this,
var x:List.<Concepts> = new List.<Concepts>;
for ( i=1; ++i<1000000; )
x.Add( new Concept() );
you now have a million of the STRUCT Things. If you then do this
x = new List.<Concepts>; // point "B"
All one million of the structs go away.
So, thats all very well. Question: if you have a Unityscript Class (NOT a struct),
class Abstractions // SIC .. a class, not a struct idiom
{ }
and then you do this,
var y:List.<Abstractions> = new List.<Abstractions>;
for ( i=1; ++i<1000000; )
y.Add( new Abstractions() );
you now have a million of the CLASS Things. If you then do this
y = new List.<Abstractions>; // point "D"
WHAT HAPPENS?
ie: do you have to eliminate them all manually first (in some way)?
FTR. is the answer exactly the same if you use a natural array?? As a further curiosity, Javascript gurus, is it the same in "standard" Javascript? Thank you for your attention to this lame Unityscript question...cheers
Mike ...
in view of your superb explanation. {It didn't even explicitly occur to me it's a GC environment, of course it is - thanks!}
My questions to you,
(ONE) at point "B" (see 'comments' in the example code) when I make x point to a new List, DO I HAVE TO / SHOULD I DO ANYTHING regarding the million Concept structs which the old List at x pointed to?
and then,
(TWO!) at point "D" when I point x to a new List, same question .. should I / do I have to do anything to the old million Abstractions classes ?
Thank you!
The further question, 1B and 2B:
in fact, IS THERE a way to indicate to the GC system in this environment, that I particularly don't need the million structs (or classes) any more?
Or is that meaningless, it just counts references itself, does so safely, and that's it ?
On some systems there is often a concept like say a "pool" of references, you can urge the GC system to empty out the pool, when you feel it is a good idea as a human.
Final further question: and in view of all that, is there really any difference between using either structs or classes in the example given? Does it decrement the GC once more, or something, for structs, or?? they're just the same and there's no issue to worry about there?
Thank you for being an expert !!
Buy this!
So at One/Two you do not have to do anything. You could force a garbage collection and the memory would be freed.
Generally speaking I'd say don't GC manually - you can, but it may cause problems. So I would normally not do anything when you switch that list reference.
However, there could be situations where you knew you had time for GC and you wanted to actually force the issue (between level loads maybe?) - you can do this by calling GC.Collect() - which does its level best to free as much memory as possible from all generations. Just be aware that you always run the risk of promoting some short lived objects that happen to be in memory and temporarily referenced to a later generation - so don't do it all the time :)
Now I'm not sure how UnityScript is working when you inherit from ValueType - as in I am not 100% sure that it is the same as a c# struct - but presu$$anonymous$$g it is then the memory allocated is in one big block (because structs work that way, they aren't references, they are actual memory blocks). A list will keep allocating blocks for the structs, discarding them when they run out of expansion space and making another one - this could certainly lead to more memory fragmentation than using classes. In general I don't use structs unless I want the block to work that way (especially when interfacing with native code this can be useful).
Now the thing about GC is that it isn't doing reference counting - it's weirder than that :) This is generally good news because if you have a child object with a reference to its parent, and the parent object has a reference to the child you get an unreleasable reference if you use counting. GC does not have that problem. It uses a reachability test to see if the actual running code can see any of those objects and if it can't it can be freed.
I should just add that in C# at least you can do a lot of things to do with how the members of a struct are laid out - like packing things into bytes etc where classes will align their members on boundaries that are fast for the processor - meaning if you want the smallest thing possible that represents your data then a struct, and some fancy attributes to pack it, is the way to go.
Glad to be of help :)
I know you're not much of a book fan - but I can't really not mention Jeffery Richter's brilliant book CLR via C# which is just massively useful when you get down to the nitty gritty stuff like how garbage collection works and what is going on with Delegates etc etc etc. Not much to do with Games, and not a cover-to-cover read perhaps, but it's accessible, clear and shows you some inner workings that at times can make a big difference.
BinaryFormatter.aspx) is the system binary serializer - it reads and writes public and private members of classes and structs. It ain't particularly fast though.
You can use it with a $$anonymous$$emoryStream to deep copy objects. It also isn't much good for copying the whole of a Unity GameObject, but it will work on your own stuff.
Answer by whydoidoit · Jun 12, 2012 at 08:56 AM
Actually in neither circumstance is the memory actually freed immediately - it's just available for Garbage Collection by .NET. UnityScript is different to JavaScript in this regard - but how actually varies by JavaScript implementation.
The Garbage Collector runs many times during execution - using a thing called Generations. Generation 0 is collected every time it fills up - and it fills up quick because its only around 256KB - the Garbage Collector tests for reachability of objects - i.e. does something have a reference to that object, and if it does, does the thing that has a reference have a reference to it etc etc etc
Anything that has a reference at the time of collection moves to the next higher Generation - Generation 1 is about 1MB and when it fills up then it is collected. The worst nightmare for a GC system is short lived objects getting moved to higher generations and it's that which causes Generations that aren't tiny to be collected and the game to glitch.
So in your example, there is no need to destroy the class when it becomes unreachable. Each element will be collected when its generation is collected. That might not be all at the same time of course. Presuming things that derive from ValueType are held contiguously in memory - the difference is that the structs held in an array would cause the entire array to be collected at the same time, because it is effectively one thing.
Lists grow as you add things to them, so the actual slots that hold the references to classes will be collected many times as the system decides on the next size of block to hold them in.
I just like to add that you actually can't destroy managed objects ;) They are always removed by the GC. Unity's UnityEngine.Object.Destroy() function works only for objects derived from UnityEngine.Object.
.NET has an IDisposable interface which allows you to free non managed resources when they aren't longer needed. This is important for example when using system file-handles. If you open a file handle the file is locked until the filehandle is closed. When you don't close it manually (a lot people forget it), it's closed when the File object is GC collected. This can lead to a very strange behaviour / error.
A very good point :)
If using C# it is a good idea to wrap calls to things that support IDisposable in using() {} statements. This is syntactic sugar for try() finally{} blocks that automatically call IDisposable.Dispose on the contents of the using:
using(var disposableThing = new DisposableThing())
{
...
}
Your answer
Follow this Question
Related Questions
What should i learn for unity C# or UnityScript? 4 Answers
Closure does not work in Unity JS functions? 1 Answer
Collide detection with tag [JS] 0 Answers
Creating a dynamic array of objects of custom class 1 Answer
Make a command run only once 1 Answer