-
[RESOLVED] Remove or Reuse?
Hello All,
I'm going to ask a VERY general question, is it "better" (in terms of resources, speed, memory, garbage collection) to remove objects or reuse them?
It's my understanding that removing all references and "null"-ing an object makes it ELIGIBLE for garbage collection, but generally, without getting all work-around and hackish, there's no way to FORCE the object to get garbage collected.
So, I was wondering would it just be "better" to re-use the object, instead of "deleting" the object when I know I will need another object just like it at some point in the future of the application?
-
Senior Member
If you have a Loader and you load various images/movies of course reuse it. Regarding other objects it is not quite clear to me which objects you mean. Usually you remove objects when they are not needed any more when at the same you also create new objects like in a invader game.
- The right of the People to create Flash movies shall not be infringed. -
-
Originally Posted by cancerinform
If you have a Loader and you load various images/movies of course reuse it. Regarding other objects it is not quite clear to me which objects you mean. Usually you remove objects when they are not needed any more when at the same you also create new objects like in a invader game.
Yeah, it's kind of an innocuous question/issue.
But, the invader game is a perfect example.
Let's say that creating a new invader is a "complex" process, i.e. maybe it involves adding listeners, positioning it, and just several setup steps.
Once the invader is shot down, in order to remove the invader object, it may also take several "complex" steps... if you don't just want to rely on weak references etc.
So, if this is how we create an Invader:
Actionscript Code:
// Create an invader var myInvader:Invader = new Invader(); myInvader.addEventListener(Event.DESTROYED, onDestroyed, false, 0, true); ... myInvader.x = 0; myInvader.y = 0; ... addChild(myInvader); ... myInvader.attack();
Then, if the Invader is destroyed, why should I remove the Invader and then create a brand new Invader like this:
Actionscript Code:
onDestroyed(e:Event):void{ myInvader.removeListener(Event.DESTROYED, onDestroyed, false); ... ... removeChild(myInvader); myInvader = null; }
// Add a new invader myInvader2:Invader = new Invader(); myInvader2.addEventListener(Event.DESTROYED, onDestroyed, false, 0, true); ... myInvader2.x = 0; myInvader2.y = 0; ... addChild(myInvader2); ... myInvader2.attack();
Instead of just reusing the 1st Invader like this:
Actionscript Code:
onDestroyed(e:Event):void{ myInvader.visible = false; myInvader.x = 0; myInvader.y = 0; myInvader.visible = true; myInvader.attack(); }
The 1st example seems to have a greater chance of leaving superfluous listeners or references to the 1st Invader. Also, even if all references have been successfully removed, the 1st Invader is still going to hang out in memory until Flash is ready garbage collect.
So, I was just wondering, since the 1st Invader is just sitting around waiting to be REALLY deleted, why not just reuse the 1st Invader object instead of creating a 2nd... thereby possibly introducing a situation where there are 2 invaders in memory, but only one is "active"?
ps. In reality, I realize I wouldn't have to duplicate code every time I add an Invader, and there are better ways to write the code.
But, for the purposes of this example, my question pertains to the concept/differences between removing an object (and all the necessary steps need to do so) and reusing an object.
-
You can have an identity variable as an uint that holds the number of myInvader. In the function onDestroyed, where you remove myInvader, you can find the number of myInvader and save that number in the identity variable and add 1. When adding a new invader, combine "myInvader" and the identity number variable to create a new instance, as if you are making new bullets using duplicateMovieClip.
-
It is almost always more efficient to re-use an object rather than throw one away and build another just like it. The general principle at work here is an "object pool" and you can learn more by searching for that phrase.
You do not need to do any of the identity number stuff that flashmed is suggesting, which seems to be aimed at creating a unique instance name for the instance. You don't need to give them names at all, so you don't need unique names. Instead, just put your instances in a collection like an Array or Vector. Maybe one collection for live instances and one for "reserve" instances, depending on what sort of processing you need to do on the live ones, and the expected ratio between live and inactive.
-
Senior Member
5Tons being right as usual, I just want to add that loading is the critical factor here, and be aware that if you're dealing with BitmapData objects, you have to copy them in order to safely use them in multiple Bitmaps. If that's the case, your pool should be "rolling" -- essentially a vector full of BitmapDatas that clone a new one on the end when one is requested and de-reference/empty/delete them when they aren't in use, keeping a buffer for a likely number to be created at one time so you don't see a freeze while the engine tries to duplicate and instantiate ten of them at once. How you actually implement this depends on the game, but the pool doesn't have to remain one size, and you need a method to actively prune it so that it doesn't just gobble memory.
-
Two more comments - first, I'm assuming this is similar to the classic space invaders where you will have a finite number of enemies (5 rows of 11 guys) - rather than destroying and creating new guys for every level or restart - just instantiate the max guys you'll need one time and "turn them off" when they're dead - this way your memory footprint is fixed. Obviously that's a pretty specific case but valuable if the conditions fit.
Second - I ran some benchmarks a while back on the functions in the Point class - of the methods, roughly half of them operate on the existing Point object, the other half perform the math and return the results as a new Point object. The functions that allocate new points take about 13 times longer to execute than the in-place methods.
Please use [php] or [code] tags, and mark your threads resolved 8)
-
Originally Posted by 5TonsOfFlax
It is almost always more efficient to re-use an object rather than throw one away and build another just like it.
Thanks, ActionScript abounds with exceptions, obviously... but in general, I was thinking this as well.
-
Pumpkin Carving 2008
I realize this has already been resolved, but I just thought I could add my two cents for anyone finding this thread from the search.
As has already been stated, it's generally a better idea to reuse common objects rather than creating a new one because of the overhead of memory involved. This is no more true than in Flash where memory is limited and optimization is a must.
What I typically do for object pools is to create a "factory" class. This class usually has only a few members and methods:
Members:
- Private Array "pool" - Holds any objects not in use.
- Private Array "active" - Holds any objects in use.
Methods:
- Public Function getObject() - Creates a new object if pool is empty; or returns an object spliced from the pool. Adds a reference to the returned object into the active array.
- Public Function killObject(o:Object) - Returns Void. Finds this object in the active array, splices it out, and injects it back into the pool for use later (if the object class contains a "reset" method for reinitializing this object to default values, it is called here.
A simple example:
Code:
public class BaddieFactory {
private var pool:Array;
private var active:Array;
public BaddieFactory() {
pool = [];
active = [];
}
public getNewBaddie():Baddie {
var b:Baddie;
if (pool.length == 0) {
b = new Baddie();
} else {
var b:Baddie = pool.pop();
}
active.push(b);
return b;
}
public killBaddie(b:Baddie):void {
b.nullify();
for (var i:int = 0; i < active.length; i++) {
if (b == active[i]) {
pool.push(active.splice(i, 1));
break;
}
}
}
}
/*USAGE
var bFactory = new BaddieFactory();
var b:Baddie = bFactory.getNewBaddie();
stage.addChild(b);
b.goDoStuff();
...baddie dies...
bFactory.killBaddie(b);
*/
The 'Boose':
ASUS Sabertooth P67 TUF
Intel Core i7-2600K Quad-Core Sandy Bridge 3.4GHz Overclocked to 4.2GHz
8GB G.Skill Ripjaws 1600 DDR3
ASUS ENGTX550 TI DC/DI/1GD5 GeForce GTX 550 Ti (Fermi) 1GB 1GDDR5 (Overclocked to 1.1GHz)
New addition: OCZ Vertex 240GB SATA III SSD
WEI Score: 7.6
-
Originally Posted by joshstrike
... keeping a buffer for a likely number to be created at one time ...
buffer?
By this, do you mean storing 10 objects in the Vector and keeping them ready to go... even though most of the application will only need 1 or 2 of those objects at a time, but in a specific state the App might need 10 at once?
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|