AS3 qestion about removing objects and memory/garbage collection - actionscript-3

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.

Related

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.

Which way is better to define functions in AS3?

From the performance point of view, which function definition is better/faster? Making an object and adding functions to that, or making functions one by one?
var myCollection:Object = {
first: function(variable:int):void {
},
second: function(variable:int):void {
}
}
myCollection.first(1);
or
private function first(variable:int):void {
}
private function second(variable:int):void {
}
first(1);
The latter. The performance hit will be negligible, except on a massive scale, but the second one will be slightly faster.
Basically it boils down to scope. To get a function from an object, you have to find the memory reference to the object within the scope of the class and then find the memory reference to the function within the scope of the object. With the second, you just have to find the Function object (all functions are objects) memory reference within the scope of the class.
The second method cuts out the middle man, essentially, in identifying the correct function. Now, each one will be found in less than a millisecond. As far as you are concerned, it is instant. But if you are doing this 100k times in a row? Yeah, you might see a bit of a performance boost by declaring within the class.
As an additional note, you are also adding another object to memory with the first one. Add enough of these (again, needs to be on a massive scale), and you will see a slowdown just from the superfluous objects stored in memory
You should also look at usability and readability, though. Declaring in an object means that the functions are not available as soon as the class is instantiated so you have to be careful you don't call the function before the object is instantiated. Additionally, you would lose code hinting and it is not the common way to write your code (meaning another dev, or even yourself a year from now, would have to figure out how it is working without any help from a hinter or from the standards they have already learned before they could do any modifications)

Actionscript 3.0, using FlashDevelop: local variables. Can they be mistakenly created ad infinitum?

Riddle me this: I have my MouseEvent.MOUSE_DOWN which calls mouseHandler. The latter looks something like this:
public function mouseHandler(evt:MouseEvent):void
{
var p:Point = new Point(mouseX, mouseY);
var objs:Array = new Array(getObjectsUnderPoint(p));
}
Now what I want to know is thusly: will the objs array and p point be overwritten every time, simply causing the previous objs array and p point to be wiped and a new one generated, or...does it just create a new array and point over and over and over? Of course if I trace(objs) it gives me the expected results, but am I chocking up the system in the background without realising? Your expertise would be appreciated.
EDIT: well after learning a fair bit from the answerers -thanks btw- that made me think of something else and, a quick search later, found a way to theoretically reliably remove the references:
var a = null;
Now I appreciate that this is probably not needed as they'll be GCed at the end of the function, but considering it takes two ticks to write, better safe than sorry, no?
It works like this from what I understand - references for these variables will be lost after function will end. The values will be GC'ed then eventually.
If you will call the function second time, the new references will be created, and filled with new data, the values of previous references hovewer, may still exist in memory, and wait for Garbage Collector, but that may not necessarily happen! If they have attached listeners, the Flash Player will think that they are still useful, so they will exist in the memory to the end of the application run and listen, and even react to events - even if you theoretically cannot access them anymore.
Edit:
In your case whats happening is that you are creating two references that will disappear at the end of the function. They are not related to event listener, the listener creates them, but is not attached to them so it won't stop GC from collecting them after function will end. You creates an array of references, but that are just references to other objects that values are referred in other places (like the display list), if the array alone is not referred anywhere outside of this function, it should be GCted.
Since p is an object, not a primitive, the memory allocation for it will come from the Heap (and therefore need to be garbage collected) instead of the stack like local primitives (and are wiped once the function ends.
So new memory will be allocated every time this function is called, which will temporarily increase memory usage until they get GC'd, but the amount is probably insignificant (assuming that array isn't massive!).

Why Linq to Sql have used this line while creating a property

I was reading Linq to Sql. Here I created a dbml file where I found that an autogenerated property has been created
[Column(Storage="_RecursionLevel", DbType="Int")]
public System.Nullable<int> RecursionLevel
{
get
{
return this._RecursionLevel;
}
set
{
if ((this._RecursionLevel != value))
{
this._RecursionLevel = value;
}
}
}
Here why if ((this._RecursionLevel != value)) line is written. What is the purpose. Why not directly assigned the value. What benefit they got
The garbage collector keeps track of memory regions that are written to since the last GC. If a region is not written to, the garbage collector can skip a lot of checks.
A simple assignment, marks the memory as dirty, even if the memory written contains the same value.
Check this article. Read from "Making Generations Work with Write Barriers" and "Too many object writes".
It's basically checking to see whether the value you are attempting to assign to the property is different from what it currently is. It will then only make the assignment if the value is different. Presumably this is an optimisation that saves unnecessary assignments when they are the same and stop any "OnChange" events firing for no good reason.
Usually with linq to sql classes (or at least when I used 'em) there's also a propertynotification event fired. Sooo I'm assuming the line firing the event is missing.
Because if the value wasn't changed, no need to change it and thus no need to fire that event.

Removing all references to an object removes event listeners inside that object?

When I have an object, removing all references to it is enough to sign it up for the garbage collector, atleast that's what I heard. Eg.:
removeChild(object);
object = null;
I'm still a bit confused though, because does this mean that the event listeners made inside this object's instance are also automatically removed? Or is there anything I need to do?
Ah, you've hit on the crux of memory management in managed code: if you're an object, and you have a reference to another object (even if it's only in the form of an event listener), then you are at least one reason that object won't be removed from memory during a GC.
For display objects, and in my experience pretty much anytime you want to subscribe to an event dispatcher but not be responsible for that dispatcher's remaining in memory, you should add your event listener with the weak reference option:
myPublisher.addEventListener("myEvent", myHandlerFunction, false, 0, true);
In just about every situation I encounter these days, "false, 0, true" (where true means "use weak reference," and which translates loosely as "add this listener, but don't make it a reason for the dispatcher not to get cleared from memory" -- see the docs for more information) is the proper way to add event listeners. Very few textbooks or documentation snippets illustrate this approach for some reason, which is unfortunate, because it makes for a much more intuitive memory-management experience. I'd suggest using it as the rule rather than the exception.
Hope it helps!
an important thing you should consider is that if an object O has eventhandlers, i.e. methods that were added as eventhandlers to E, then this also count as a reference ... unless you add the handler with weakreference ...
also if you have a closure, whose outer scope contains a reference to O, then this is a reference ...
you do not need to remove all references to O, to sign it up for GC either ... the GC also removes circular references ... it removes all "islands" in memory, if you will ... only "peninsulae" connected of the "continent" of builtin objects, i.e. Timers, the display list, I/O layer etc. are not collected ...
the last paragraph of another post of mine deals with this topic a little ...
so yeah, basically, if O gets GCd, then any event handlers get GCd, unless there is another reference to them ... etc.
hope that helped .. :)
greetz
back2dos