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

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!).

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.

Actionscript 3.0 Point Object not picked up by Garbage Collection

I have just been trying to fix a few memory leaks in my project and have discovered an interesting problem. It seems like a vast majority of my 'Point' objects are not being picked up by the Garbage Collector. Each frame it creates about 5000 new Point objects and less than 10% of them seem to ever get picked up. Even when you use code like this:
var tempPoint :Point = new Point();
tempPoint = null;
Even if I repeat it over 500 times, only a tiny fraction seem to be erased. This is really stating to get on my nerves now and I was wondering if anyone has encountered this before, knows how to solve it / get around it, or cares to enlighten me on what exactly I am doing wrong.
Would love to know anyone's thoughts on this
ps. I am using The Miner to check the resource usage
Edit: Have now done a quick check where I had the program running for about an hour and although the memory usage went up about 140MB it did start garbage collecting at this point and did not go past that. So they will be picked up but not until you have several million created ;)
How long are you waiting for them to be erased?
If you are creating 5000 new objects per frame, it's probably a good idea to use an object pool.
class PointPool {
private var _points:Vector.<Point>;
public function PointPool() {
_points = new Vector.<Point>();
}
public function createPoint(x:Number, y:Number):Point {
var p:Point = null;
if( _points.length > 0 )
p = _points.pop();
else
p = new Point();
p.x = x;
p.y = y;
return p;
}
public function returnPoint(point:Point):void {
_points.push(point);
}
}
Just a thought :)
I will quote Grant Skinner to answer your question:
A very important thing to understand about the Garbage Collector in FP9 is that it’s operations are deferred. Your objects will not be removed immediately when all active references are deleted, instead they will be removed at some indeterminate time in the future (from a developer standpoint).
[...]
It’s very important to remember that you have no control over when your objects will be deallocated, so you must make them as inert as possible when you are finished with them.
So, what's happened with your code? FP created something near 5000 instances of Point. If you look the memory usage over time you may notice that it will drop to the initial value after a few seconds.
The best way to avoid this behaviour is to pool the created objects and reuse them instead of creating a new one.

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.

temporary variables

I would like to know what's the difference when I write a temporary variable like this (these are just examples):
version1
for each tempEnemy in enemyManager.enemies {
var tempX:int = tempEnemy.x;
}
or this:
version2
for each tempEnemy in enemyManager.enemies {
tempEnemy.oldX = tempEnemy.x;
}
What's wrong and right? Currently I write it like version 2 and I'm not sure if I should change it to version 1. Can someone help me out with this please? I know most developers write like version 1 but I'm a little bit confused because I am totally unaware about version 1. If I use version 1 does that mean that my value is stored explicitly in a temporary variable that is cleared in every cycle?
Also...
Adding the :variableType (int, String, Number etc) aids in code hinting and debugging.
In version 1 the declaration:
var tempX:int
defines a variable that lasts only as long as that iteration of the for (or for-each) loop it's in. Each iteration tempX is defined, given a value from an Enemy object, and at the end it is left for garbage collection.
In version 2, you reference two variables attached to an Enemy object referenced by the temporary variable named tempEnemy.
In both versions the reference to the Enemy object, tempEnemy, is reassigned the next iteration's Enemy object.
Each method has its advantages. From a memory standpoint, version 2 is probably better, since it changes an existing variable over and over rather than creating a new variable that's discarded at the end of each iteration. On the other hand, version 1 doesn't require you to have oldX defined in its class variables, which can often get mucky enough without these sorts of variables.
Best practices with code are based off of (a) working with other programmers, who need to be able to read and understand the code, and (b) leaving a project and coming back to it later, where you'll need to be able to read and understand your own code. For short projects you don't plan on sharing, version 2 is okay (and probably more memory-efficient), but any large project should use something more like version 1.
Another consideration is, are you going to use that variable anywhere other than the function where it is defined(set)? If not, you don't need to store it in the object, which points again to version 1.

How can I unset an (unsigned) integer in ActionScript/Flex 3?

I have a class which is called a number of times. When the application goes to the next stage these all have to be unloaded. Because of that, I created an unload() method in the class.
The problem is that I can't seem to set my uint variable "charId" to null in order to "unset" it. The "delete" command is not possible either as that is only applicable for dynamic variables or something in that kind of way.
Now I wonder, how am I supposed to unset this variable, so it's memory will be re-allocated later on?
The class's unload method:
public function unload():void
{
trace("Unloading character with charname '" + charName + "'.");
enterButton.removeEventListener(MouseEvent.CLICK, enterClicked);
removeChild(enterButton);
enterButton = null;
charName = null;
charId = null; //this is possible but not recommended - what's a better way?
lobbyInterface = null;
}
So yeah, it's practically possible as it changes the variable type - however it's not recommended and raising a warning. So, what's a better way to do it?
Note that this object is also unloaded in it's parent. Does that also free all these variables from memory?
uint, int, Number and Boolean are not nullable in AS3. Number can be NaN, but that is really the best you can get. int and uint are always just 32 bit, so you can't stuff a null-reference in there.
The type of cleanup you are trying to do cannot be accomplished since AS3 has the concept of sealed classes. A sealed class has a fixed size in memory. When it comes to instance variables, think of it as a C struct, you can only dump all of it, or nothing. You can do anything in C of course, it's a fixed block in memory, an entity of one reference per variable.
What you want to do is only work with dynamic variables, which are maintained differently.
You don't need to do this sort of cleanup since Flash has garbage collection like most runtimes nowadays. It also deals with nested and circular references, the only thing you have to be sure about is, that you delete any "outer" references to that class. Things that are generally not collected are objects on the display list, running timers and intervals, and I/O related stuff. As soon as you have a reference chain from there to your object, it will not be collected.
Let us say you have an object A with an event handler for a mouse movement on an object on some list, referencing an object B. B will not be collected, but as soon as there is no chain leading to an object, it will be collected (sooner or later, the GC is quite lazy. But the more memory you use, the more it does its work).