as3: does array splice delete an object completely? - actionscript-3

I have a lot of display objects in an array that I'm constantly adding and removing from stage. When removed they are not used anymore.
Considering the displayObject is not on the display list, and has no event listeners... will it be garbage collected if I use splice to remove it from the array?
Is it safer if I null the object first?
myArray[2] = null;
myArray.splice(2,1);

As long as there are no remaining references to the DisplayObject then yes, removing it from the array using splice, or even just setting it to null will allow it to become a candidate for garbage collection.
Update: Setting the item to null before removal from the array is redundant and will make no difference.

If you need better performance I suggest you using pools instead of creating lots of objects and putting them in array. Use some linked list implementation instead of splice() operation, which is really slow.

Related

libGDX Array class benefits

The javadoc of libGDX Array class says: A resizable, ordered or unordered array of objects. If unordered, this class avoids a memory copy when removing elements (the last element is moved to the removed element's position).
Is the elements removal improvement the only advantage of this class or there are others?
In other words - if I'm not planning to remove elements from my list at all can I live with ArrayList?
Array is actually not the only "replacement" of standard Java collection classes. There are many more like ObjectSet or IntIntMap. You can find all of them here.
They are mostly optimized to avoid garbage collection as much as possible. They do this in many ways.
One way is the one you already pointed out, by trying to avoid memory copies when possible, for example in case of a removal of an element in an Array.
Furthermore they re-use the iterators. The standard java collections do not do this, which is why there will be a new Iterator being created every time you are iterating over the collection.
Another way is the use of primitives, which avoids the creation of Objects due to autoboxing. IntIntMap for example has int keys and int values. The standard java HashMap<Integer, Integer> cannot deal with primitives which will result in many autoboxed int -> Integer.
You should always try to stick to the libgdx classes whenever you can, especially on mobile devices. On desktop the garbage collector is usually so fast that you won't notice it, but even there it can result in ugly FPS-lags.

Using retain and release for Objects

Are there any general guide lines for using retain and release for objects in cocos2d-X ? When creating objects in a function, is it true that the functions memory is cleaned up the second the function returns. When a object is created, calling the retain function of the object, will retain object beyond the function return ?
Kind Regards
Generally in c++ you have this behaviour:
void foo() {
Object a;
Object *pA = new Object();
(…)
}
This would result in a being destroyed automatically at function end, as it was allocated on stack. The *pA would not get destroyed, as it was allocated on the heap (thus, you only loose the reference to it, but the object itself still lives).
Cocos implements a thing called "Automatic Reference Counting" : each CCObject has a reference counter and two methods retain() and release(). The way this works is, that every time you create an object, it gets registered in cocos structers (CCPoolManager). Then with every frame (between them being drawn) there is a maintenance loop which checks the reference counter of all objects : if it is 0 this means (to cocos) that no other objects reference it, so it is safe to delete it. The retain count of an object is automatically incresead when you use this object as an argument for an addChild function.
Example :
void cocosFoo() {
CCSprite *a = CCSprite::create(…);
CCSprite *b = CCSprite::create(…);
this->addChild(b);
}
What happens here is this :
Two CCSprites are created, cocos knows about them.
The b sprite is added to this object (say a CCLayer)
The function ends, no objects are destroyed (both of them being on heap).
Somewhere between this and next frame, the maintanance gets run. Cocos chcecks both sprites and sees that a has reference count == 0, so it deletes it.
This system is quite good, as you don't need to worry about memory management. If you want to create a CCSprite (for example), but not add it as a child yet, you can call retain() on it, which will raise its reference counter, saving it from automatic deletion. But then you'd have to remember about calling release() on it (for example, when adding it as a child).
The general things you have to remeber about are :
Each call to retain() by you needs to be paired with release().
You generally shouldn't delete CCObjects yourself. If you feel that you need to, there is a conveniece macro : CC_SAFE_DELETE(object)
So to answer your questions in short :
Are there any general guide lines for using retain and release for objects in cocos2d-X ?
Yes, you should generally not need to do it.
When creating objects in a function, is it true that the functions memory is cleaned up the second the function returns.
Answer to this is the whole text above.
When a object is created, calling the retain function of the object, will retain object beyond the function return ?
Yes, as will adding it as a child to another (retained in any way) object.
Here is the thing,
cocos2dx has an autorelease pool which drains the objects which have retain count=0 which is a variable to keep in check the scope of the cocos2dx object.
Now when you create new object using the create method it is already added to the autorelease pool and you don't need to release it or delete it anywhere , its like garbage collector in java, takes care of garbage objects behind your back.
But when you create new object using 'new' you definitely need to release it in its destructor or after its use is over.
Second thing,
when your object is added to the autorelease pool but you need it somewhere else you could just retain it , this increments its retain count by one and then you have to manually release it after its use is over.
Third Thing,
Whenever you add child your object it is retained automatically but you don't need to release it rather you remove it from the parent.

AS3 Return Object currently under another Object without HitTestObject

Is it possible to return the Object that is underneath/in contact with another Object without using hitTestObject ?
I'm wondering if I can remove the need to loop through an array of 'active' Objects and simply get the instance that's underneath at any given time. Possibly using as3 events ?
many thanks SC
You can use the getObjectsUnderPoint() method of the DisplayObjectContainer class.
Be carefully, using a getObjectsUnderPoint().
getObjectsUnderPoint() return types Array. this mean specify Point above all DisplayObjects return. sometimes you do not want to get the value. So the objects in the array must be verified. Faced this problem, especially DisplayObjects when they overlap or if you load the other swf

AS3, FlashDevelop: Booleans. How do you GC them?

I'm using AS3 and FlashDevelop, and I cannot seem to convince my FlashPlayer/AVM to GC it.
I tried the pretty standard options:
myboolean = null;
delete(myboolean);
But for the null it says "col: 14 Warning: null used where a Boolean value was expected."
And delete I get "col: 11 Error: Attempt to delete the fixed property allDone. Only dynamically defined properties can be deleted."
And this is considering the Boolean is definited within a method as such:
var myBoolean:Boolean = false;
I appreciate that since it's within the method, when such has run it's course it should get garbage collected, but I like to be certain, and why can't I GC the Boolean when I've done the same for int, Array and Point within another method of the same class? Isn't Boolean also an object?
So if anyone knows how to GC the Boolean please let me know.
Basically like Jonatan Hedborg here says you don't directly control what is garbage collected.
My guess is you're from a c/c++ background or the like where you are responsible for maintaining memory more strictly and directly, this isn't exactly the case with AS3 and Java; though memory management is still very important it's handled more at an Object level. Although Boolean extends from Object read here regarding primitive types:
Null data type The Null data type contains only one value, null . This
is the default value for the String data type and all classes that
define complex data types, including the Object class. None of the
other primitive data types, such as Boolean, Number, int and uint,
contain the value null . Flash Player and Adobe AIR will convert the
value null to the appropriate default value if you attempt to assign
null to variables of type Boolean, Number, int, or uint. You cannot
use this data type as a type annotation.
http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7f88.html#WS5b3ccc516d4fbf351e63e3d118a9b90204-7f82
In both cases you do have mechanisms such as nulling references to detach objects from the graph of all of the active objects which means they'll be garbage collected at the next scheduled run of the garbage collector (which can be forced but it isn't really recommended, the configuration for the JVM or AVM in this case will handle it based on the system it's running/executing in).
nulling an object will allow it to be garbage collected but you shouldn't really be concerned about individual primitive properties. There's a good article explaining some details on garbage collection in AS3 here (I would leave a an abstract but the whole page is pretty good, main points I suppose being garbage collection isn't necessarily 100% straight-forward but with some effort can be managed):
http://tomgabob.blogspot.com/2009/11/as3-memory-management.html
Basically the way it works is the FlashPlayer or whatever virtual machine is running your (byte)code has a graph of all the objects that have been created and that there is a current reference to.
It also has a memory limit for what it can use based on the environment (config etc.) so the GC has algorithms setup to figure out when it should attempt to garbage collect. You should primarily be concerned with nulling references to objects you no longer need, and really this isn't too big of a deal if your application isn't fairly complex, or your hardware isn't extremely restrictive with regard to RAM.
So the concern shouldn't be making the GC run too little or too much, but creating references that are never removed (addingListeners and not removing from objects that should be collected, or simply having references to them within collections etc. after they are no longer needed). Again the article above explains this in a bit more depth.
Where are you using the boolean? The only way to make sure primitives are GC'ed is to ensure the class it's used in is collected.
There are 2 errors in your reasoning:
'delete' can only be applied to dynamic objects, not class members or local variables; in these cases, just set the member/variable to null,
value types (boolean, number, string) don't need to be GC'd; in some cases Flash will create temporary 'boxing objects' which will be automatically collected so you don't have to worry about those.

AS3 qestion about removing objects and memory/garbage collection

I have a routine that repeatedly builds and rebuilds a big dynamic movieclip full of buttons called "bigList". When it rebuilds, it first attempts to trash bigList so that it doesn't repeatedly add instances of it to the stage (which it was doing for a while).
I have come up with this code which seems to do the trick:
if (bigList.stage)
{
trace("...bigList exists, better trash it");
bigList.parent.removeChild(bigList);
bigList = null;
bigList = new MovieClip();
trace("...done trashing.");
}
It appears to work... what I am concerned about is garbage collection and memory leaks and such. By doing the above, am I PROPERLY getting rid of the old bigList and replacing it anew, or is there going to be data sitting around in memory that I have to deal with?
To add to that, every time it builds bigList, it adds dozens of dynamically generated mc's, each with an event listener to check for clicks. When I trash bigList each time, are all of those instances and listeners sticking around as well?
Do I need to traverse all of the children of bigList and trash them as well, and their listeners? Is there an efficient way to do that, trash a top-level object and all of its sub-objects and listeners, or am I already getting that with the code I have?
Thanks so much!
The great thing about the garbage collection is that it does most of the work for you. All you have to do is guarantee that there's no references to an object, if that is true then the GC will delete the object from memory at it's own pace (you can't force it to empty at your own chosen time).
From your code sample above, you're doing it great, only one small change I would suggest:
if (bigList.stage)
{
trace("...bigList exists, better trash it");
this.removeChild(bigList); // "bgList.parent" is the same as using "this"
bigList = new MovieClip();
trace("...done trashing.");
}
You don't need to set the variable to null as putting a new MovieClip object into the variable will mean the old object has no reference.
Also, there's no need for the bgList.parent usage as you're already in the parent class. You can even remove the this. to ease readability and reduce clutter but it's good practice to leave it in.
So besides those small recommendations, you're doing a fine job and, based on your sample, you shouldn't have any memory leaks caused by that segment of code.
Adding onto xLite's answer, you can use System.gc() while debugging to force the garbage collection process and check if you've been removing references properly - generally by checking the total RAM usage immediately afterward via System.totalMemoryNumber.