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.
Related
How to implement Undo Redo operation in flex 4 for maintain history?
I'm working with flex UIComponent and DisplayObjects for creating and editing diagrams,but
in flex there is no way to handle user operation history directly.
there is any idea to achieve this?
You could implement the Command Pattern for all actions with execute and undo methods, and queue them up.
so when the user wants to do some thing - lets say create an AddFiveToTotal class and executes:
public method execute():void{
totalModel.add( 5 );
}
This class would then be stored on a FIFO queue.
if the user needs to undo the command would be popped and the undo function called:
public method undo():void{
totalModel.subtract( 5 );
}
for redoability, don't pop, just iterate the queue
also take a look at the Memento Pattern
If you are using any of the currently popular MVC(S) frameworks you will undoubtably find a util that some one has already created
You can acheive with help of memento pattern. It hard to track all properties better you can what are property need to use for undo/redo operation.
Memento Design pattern
Memento pattern
Demo sample with source code http://www.flairpy.com/mementoPattern/MementoSample.html
There are several ways you can address to this problem. First is to keep the states of your whole canvas in a Vector (I mean have a listener for all the things user can do on the stage and saving the state after a change) and then have an index of current state saved, so that you could move through your Vector and put the needed state on the stage. This is the easiest way to approach undo/redo functionality, but beware that you'll have to make clones of objects a lot and this will become a memory hog if you're going to deal with a lot of objects or a lot of undo/redos.
The second approach is to only keep what changed in that vector, so that you won't have to create and clone a lot of objects, but only save one object in your Vector which will contain all the properties that have changed and their last values. This will get you something like this:
private var mHistory:Vector.<Object> = new Vector.<Object>();
private var mCurrentIndex:int = -1;
public function storeState(state:Object)
{
mHistory.push(state);
mCurrentIndex++;
}
public function undo():void
{
if(mCurrentIndex < 1)
return;
mCurrentIndex--;
//here you could test for values that could have changed
var item:DisplayObject = this.getChildByName(mHistory[mCurrentIndex].name);
if(mHistory[mCurrentIndex].x != undefined)
item.x = mHistory[mCurrentIndex].x;
// etc. you get the point. Note that this is only comfortable if only several things can change
}
And the call for storeState function would be like this:
var state:Object = { name:DisplayObjectName, x:120, y:20 };
storeState(state);
Again, you will have to listen to all movement and changes if you want to record them.
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!).
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.
For a game I'm attempting to develop, I am writing a resource pool class in order to recycle objects without calling the "new" operator. I would like to be able to specify the size of the pool, and I would like it to be strongly typed.
Because of these considerations, I think that a Vector would be my best choice. However, as Vector is a final class, I can't extend it. So, I figured I'd use composition instead of inheritance, in this case.
The problem I'm seeing is this - I want to instantiate the class with two arguments: size and class type, and I'm not sure how to pass a type as an argument.
Here's what I tried:
public final class ObjPool
{
private var objects:Vector.<*>;
public function ObjPool(poolsize:uint, type:Class)
{
objects = new Vector.<type>(poolsize); // line 15
}
}
And here's the error I receive from FlashDevelop when I try to build:
\src\ObjPool.as(15): col: 18 Error: Access of undefined property type.
Does anybody know of a way to do this? It looks like the Flash compiler doesn't like to accept variable names within the Vector bracket notation. (I tried changing constructor parameter "type" to String as a test, with no results; I also tried putting a getQualifiedClassName in there, and that didn't work either. Untyping the objects var was fruitless as well.) Additionally, I'm not even sure if type "Class" is the right way to do this - does anybody know?
Thanks!
Edit: For clarification, I am calling my class like this:
var i:ObjPool = new ObjPool(5000, int);
The intention is to specify a size and a type.
Double Edit: For anyone who stumbles upon this question looking for an answer, please research Generics in the Java programming language. As of the time of this writing, they are not implemented in Actionscript 3. Good luck.
I have been trying to do this for a while now and Dominic Tancredi's post made me think that even if you can't go :
objects = new Vector.<classType>(poolsize);
You could go something like :
public final class ObjPool
{
private var objects:Vector.<*>;
public function ObjPool(poolsize:uint, type:Class)
{
var className : String = getQualifiedClassName(type);
var vectorClass : Class = Class(getDefinitionByName("Vector.<" + className + ">"));
objects = new vectorClass(poolsize);
}
}
I tried it with both int and a custom class and it seems to be working fine. Of course you would have to check if you actually gain any speed from this since objects is a Vector.<*> and flash might be making some implicit type checks that would negate the speed up you get from using a vector.
Hope this helps
This is an interesting question (+1!), mostly because I've never tried it before. It seems like from your example it is not possible, which I do find odd, probably something to do with how the compiler works. I question why you would want to do this though. The performance benefit of a Vector over an Array is mostly the result of it being typed, however you are explicitly declaring its type as undefined, which means you've lost the performance gain. So why not just use an array instead? Just food for though.
EDIT
I can confirm this is not possible, its an open bug. See here: http://bugs.adobe.com/jira/browse/ASC-3748 Sorry for the news!
Tyler.
It is good you trying to stay away from new but:
Everything I have ever read about Vector<> in actionscript says it must be strongly typed. So
this shouldn't work.
Edit: I am saying it can't be done.
Here see if this helps.
Is it possible to define a generic type Vector in Actionsctipt 3?
Shot in the dock, but try this:
var classType:Class = getDefinitionByName(type) as Class;
...
objects = new Vector.<classType>(poolsize); // line 15
drops the mic
I don't really see the point in using a Vector.<*>. Might as well go with Array.
Anyhow, I just came up with this way of dynamically create Vectors:
public function getCopy (ofVector:Object):Object
{
var copy:Object = new ofVector.constructor;
// Do whatever you like with the vector as long as you don't need to know the type
return copy;
}
I am uploading files using the upload() method of the FileReference class. I want to display the current connection speed and I was wondering what was a good way to do that.
My current technique is to use a Timer every 1 mili second such as follows:
var speed:Function = function(event:TimerEvent):void {
speed = Math.round((currentBytes - lastBytes) / 1024);
lastBytes = currentBytes;
}
var speedTimer:Timer = new Timer(1000);
speedTimer.addEventListener(TimerEvent.TIMER, uploadSpeed);
and currentBytes gets set into the ProgressEvent.PROGRESS. This technique seems imprecise. I was wondering what other ways I could use to calculate the upload speed while uploading and display it in real time.
Any ideas or opinions are welcomed!
Thank you very much,
Rudy
If that code block is a copy and paste it certainly won't work as you have expected it to. You declare speed as a function within which you appear to redefine it as a number. I appreciate the Flash IDE let's you get away with sketchy grammar, but code like that is going to lead you into all kinds of trouble. Try to be explicit when writing your code.
Try something like this, replacing yourLoader with whatever identifier you assigned to the uploader:
private var speed:Number = 0;
private var lastBytes:uint = 0;
private function uploadSpeed(event:TimerEvent):void
{
speed = Math.round((yourLoader.currentBytes - lastBytes) / 1024);
lastBytes = yourLoader.currentBytes;
}
private var speedTimer:Timer = new Timer(1000);
speedTimer.addEventListener(TimerEvent.TIMER, uploadSpeed);
That should calculate how many bytes moved in 1 second intervals.
Edit:
You might like to make the interval a little smaller than 1000ms and calculate an average speed for your last n samples. That would make the number your users see appear more stable than it probably does right now. Make speed an Array and .push() the latest sample. Use .shift() to drop the oldest samples so that you don't lose too much accuracy. Trial and error will give you a better idea of how many samples to hold and how often to take them.
You can moniter the upload speed on the server and then send that data back to the client. This technique is often used for ajax file upload forms.