Using object pools

June 18, 2008 on 4:58 pm | In Actionscript, Physics |

Joa Ebert is right when he says that utilizing object pools can make your code perform a lot faster. An object pool is just a container for a bunch of pre-constructed objects that are kept in memory ready for use, rather than being repeatedly allocated and destroyed on demand.

Object pooling makes sense if:

  • you create dozens of short-lived objects in real-time applications like games
  • you need to store and share temporary data throughout complex algorithms
  • the objects are expensive to create (many fields, complex inheritance chain, nested objects)
  • the objects are expensive to remove (unregister listeners, nullify instances)

The only drawback is that memory consumption will raise, but with ridiculously low memory prices this shouldn’t be problem if used wisely ;-)

Implementation

So here is my ObjectPool.as manager class which is an attempt to create a lightweight, fast and reusable solution. The implementation is based on a circular list, and the API is very simple. Download: ObjectPool_v1.0.zip (source, example, asdoc)

EDIT
I have updated the class so it also accepts a factory for object construction.
Download: ObjectPool_v1.1.zip

First, we create the object pool:

var isDynamic:Boolean = true;
var size:int = 100;

var pool:ObjectPool = new ObjectPool(isDynamic);
pool.allocate(MyClass, size);

The isDynamic flag defines the behavior for an empty pool. If true, the pool automatically creates a new bunch of objects for you. If false, the class throws an Error to indicate that the pool is empty. The size value indicates the pool’s capacity - if the pool is dynamic, the pool grows by the initial size each time it becomes empty so it actually never dries up.

By calling the allocate method the pool is filled with 100 instances of MyClass. You can always reuse the pool for another Class by invoking this method again.

If you need to initialize the objects by passing arguments to it, you can do this with a little helper method called initialize:

pool.initialize("funcName", [arg0, arg1,...]);

This goes through every object and applies the function with the given arguments upon each object. This can also be done by reading each object, calling the function and putting it back:

for (var i:int = 0; i < pool.size; i++)
{
	var o:MyClass = pool.object;
	o.init(arg0, arg1, ...);
	pool.object = o;
}

Now to get an instance of MyClass you access the pool like this:

myObjectArray[i] = pool.instance;
//instead of
myObjectArray[i] = new MyClass();

When you are done with your object, instead of throwing it into the garbage collector, you “recycle” it for the next use:

pool.instance = myObjectArray[i];

This assumes that you are storing your instances in an array or something else because if you loose the reference, well it’s lost and can’t be reused anymore :-) And be careful not to assign the object twice, since then your pool would contain duplicates of the same object!

That’s all, pretty simple right ?

Finally, there is the purge() method, which is only interesting for pools that are dynamic. As the pool grows with the demands of the application, it can get quite big. The purge methods scans the pool and removes all allocated but currently unused objects, leaving with a compact representation.

Demo

Here is a little demo which demonstrations how the pool works internally. Actually it’s very simple. Pressing the RIGHT arrow key reads an object from the pool (first row), which is then stored in the second row beneath. Pressing the LEFT arrow key gives the object back to the pool. Pressing the ENTER key performs a purge() operation. The purple circle points to the node where the next object is read, the blue circle to an empty node where the insertion is performed.

Performance

Benchmarking revealed that it’s always faster to cache instances, even for the generic Object class. All benchmarks were done with the release player 9.0.124 on Vista, an object pool size of 100 and with 100 iterations each to get an average value.

The purple bar indicates the time needed to access the pool:

for (var i:int = 0; i < k; i++) instances[i] = p.instance;

The blue bar measures the task of reading the objects, then putting them back:

for (i = 0; i < k; i++) instances[i] = p.instance;
for (i = 0; i < k; i++) p.instance = instances[i];

The grey bar shows the time needed for creating the objects on the fly:

for (i = 0; i < k; i++) instances[i] = new MyClass();

Here my result:

Caching a native flash Object can be almost 5x faster instead of creating it on the fly.

Almost the same applies to a slightly more complex object like the flash.geom.Point class.

Creating complex objects, here from the flash.display.Sprite class, is extremely slow and up
to 80x faster when pooling.

37 Comments »

RSS feed for comments on this post. TrackBack URI

  1. Excellent blog! I’m about to benchmark your pooling implementation against my own, which is actually based on your single linked list class ;)

    Comment by amirpc — June, 18 2008 #

  2. i think i got it! very interesting, especially the sprites thing -

    Comment by vi2e — June, 18 2008 #

  3. How faster is it to use a linked list instead of an array for containing the pooled objects? Thanks for the post !

    Comment by luca — June, 18 2008 #

  4. Cool idea, love your tutorials! However the price is not the problem today with memory. The problem are the manufacturers who don’t provide 64bit drivers. That fact alone has kept me so far from using 64bit Vista. And 2 Gigs of RAM are pretty quickly fueled … but now I digress.

    Comment by sascha/hdrs — June, 19 2008 #

  5. Nice post!

    I am wondering why you are passing a class directly to the allocate method. I would say a class factory will help you in case the target class should be constructed in a special fashion.

    This would also make the initialize method not needed. You could offcourse implement the allocate method in a way that it can handle factories as well as classes.

    Greetz Erik

    Comment by EECOLOR — June, 19 2008 #

  6. Nice and clear read. Very useful indeed, especially when using a lot of entities.

    Comment by Jorrit — June, 19 2008 #

  7. I agree with EECOLOR. I think that getting an instance with a getter isn’t clear. I’d prefer using a method that suggest that some work is being done behind.
    But you’ve done an excelent work indeed. Thank you for sharing it.

    Comment by nacho — June, 19 2008 #

  8. @luca
    I don’t have exact numbers, but from my experience linked list are always faster, type safe and more elegant.

    @EECOLOR
    My motivation was to provide a very simple one-class solution, so I decided to allocate the pool with a simple class, which should be fine in most cases. But I also agree with you that a factory is a better solution, so I’ve enhanced the class with the ability to use an optional factory if the class is omitted.

    Comment by Michael — June, 19 2008 #

  9. Hello,
    It sounds very cool. I download the exemple but I found it difficult. It’s very abstract. Can you post a simple real life exemple using a new Sprite() ?
    Thanks !

    Comment by joe — June, 19 2008 #

  10. This is a nice approach. I usually do object pooling at the Factory level by maintaining a ‘dead pool’. When the factory is asked to make an object, it checks the deadpool to see if an object has been returned there, if so, returns that, otherwise makes a new one.
    But I think the nice thing about Michael’s method is that it lets you do all your expensive instantiation upfront. Does that sound about right?

    Comment by Timbot — June, 19 2008 #

  11. [...] using objects pool [...]

    Pingback by iTamt.cn » Blog Archive » 使用对象池,using objects pool — June, 21 2008 #

  12. New ActionScript Optimisations Page…

    I’ve just put up a page (see bright orange bar along the top, you can’t miss it) containing a amalgamation of all the AS optimisations I’ve come across recently while hunting around for ways to speed up code. I’ll be updating i…

    Trackback by Visual Harmonics — June, 22 2008 #

  13. [...] polygonal labs » Using object pools boostworthyisryantaylor » AS3: Allocator For Object Caching magari ti risulta utile ciau __________________ http://del.icio.us/nootropic.kint [...]

    Pingback by [Actionscript 3] problema ram - Forum Flash CS3 — July, 3 2008 #

  14. [...] instance of a GameSprite is obtained through a SpriteFactory, which utilizes Polygonal Labs’ Object Pools. Every instance references the same BlitCache, receiving the necessary image depending on its [...]

    Pingback by Red Invaders Flash Game | Final Final — July, 12 2008 #

  15. [...] pool’ and can be implemented in various ways, a good introduction can be found in this article at polygonal labs. However, beware of dangerous side-effects due to multiple references — object [...]

    Pingback by science&code » Actionscript optimization — August, 2 2008 #

  16. [...] recently read a great article on the benefits of using an object pool over at polygonal labs.  In a nutshell  it is a technique where you maintain a collection of objects which you can [...]

    Pingback by neilbrown.info » Blog Archive » Object Pooling — August, 4 2008 #

  17. I am trying to use your Pool class and I was wondering what happens with this.

    //—- other variables defined above ——–

    var o : myClass = pool.object;
    myArray[i] = o;

    var bubbleMC: myArray[i];
    blowMC.scaleX += blowMC.scaleX*10;
    pool.object = myArray[i];
    blowMC.x += blowMC+100; // Is blowMC gone?

    Comment by jason — August, 22 2008 #

  18. hey polygonal with the debug player pressing enter on the example for this causes a security sandbox violation error, looks like you left your SOS Tracer commands in and its trying to use a local connection, just thought you’d like to know :)

    all the best

    Comment by freshcut — August, 22 2008 #

  19. if bubbleMC equals blowMC (otherwise your code doesn’t make any sense) blowMC is still available as long as you keep a reference to it (through myArray)

    Comment by Michael — August, 22 2008 #

  20. This looks great! I was looking through the code in version 1.1 and thought I should tell you the method initialize in ObjectPool.as is incorrectly spelled initialze.

    A quick fix for someone when looking through the code but easily overlooked otherwise.

    Comment by bryant — October, 22 2008 #

  21. Coolt stuff! I will definitely use this. Will drop you a link if / when it gets implemented

    Comment by BubbleBoy — December, 2 2008 #

  22. [...] operations. Again to try and reduce the amount of memory PV3D was using, I implemented a custom object pooling system for textures and geometry - so that walls are re-used between different levels. The levels [...]

    Pingback by MochiLand » Blog Archive » Meta4orce: creating 3D Flash games with PaperVision3D — December, 29 2008 #

  23. [...] what was best with the older GC. Also bingo. This is why i shudder when i read things like this: http://lab.polygonal.de/2008/06/18/using-object-pools/ Right now, Flash has a pretty basic collector, and object pooling is apparently a very big win. At [...]

    Pingback by Are there any Garbage Collector improvements? | keyongtech — January, 18 2009 #

  24. [...] ??? ??? ? ???? ??? ??? ??? ? ? ????. . http://lab.polygonal.de/2008/06/18/using-object-pools/ ???? ?????? ???? ?? ?? ??? ???? ????. [...]

    Pingback by dieBuster » Memory Pooling in as3 — March, 11 2009 #

  25. Even though it is obvious that object pooling is advantageous, your documentation and examples are way too cryptic and abstract for anyone to fully understand the product of your hard work. The same goes for linkedlists and doublelinked lists. After all this hard work, it would be warranted that you give some real life examples that are well commented so that the average newbe can come to understand your thought. Remember, good code takes into consideration the dumb people, because the smart ones will either already know or not care.

    Thank you and I hope to see some usable examples soon.

    Ben

    Comment by Ben — March, 11 2009 #

  26. I agree with ben. I love all your work, however you’re way more smarter-er than me so, usually the examples you give have their own learning curve.

    Comment by onedayitwillmake — May, 2 2009 #

  27. Thanks for tutorial,
    Its really useful
    Keep it up

    Comment by Swimming pools, India — May, 4 2009 #

  28. [...] Polygonal Labs Using Object Pools [...]

    Pingback by *drawlogic » AS3 Flash Efficient Code Techniques, Vectors in Flash 10, Faster JPEG Encoding, Other Optimization Notes - interactive and game development technologies for the web - flash, flex, unity3d, silverlight, javascript [ draw.logic ] » — May, 22 2009 #

  29. I’ve been using your ObjectPool class for a little while now and it’s awesome. Thanks! I have one question/observation: If the object you are pooling requires some kind of unique initialization, the ability to grow the pool kind of breaks down. For instance, if you create a pool of objects with grow equal to true and you use up the initial allocation, as soon as the pool expands you theoretically would need to initialize all the new objects similarly. I don’t have a workaround for this and was wondering if you’ve encountered this edge case before?

    Comment by oliver — June, 11 2009 #

  30. [...] http://lab.polygonal.de/2008/06/18/using-object-pools/ [...]

    Pingback by Investigación sobre optimización en aplicaciones desarrolladas con Flex (Parte 2 – planteando soluciones) « 3wstudio — August, 12 2009 #

  31. Hey Michael, I was hoping that you could make your benchmarking source available. I’m currently experimenting with some object pooling in a physics scenario, but would like to see how the numbers for your test match up against my own on a quite a bit different machine.

    I did some of the basic tests describes here (avg. of 100 iterations of 100 object creations) but am coming up with drastically different numbers. So benchmarking against your benchmarks here would be great.

    Comment by brad — October, 14 2009 #

  32. I don’t keep the source for the benchmarks..but to compare results both approaches have to run on the same machine, with the same player on the same OS and compiled with the same compiler :-) Also the object pool described here is outdated, but I’ll try to post my new approach soon.

    Comment by Michael — October, 21 2009 #

  33. [...] http://lab.polygonal.de/2008/06/18/using-object-pools/ [...]

    Pingback by Flex and Flash Developer – Jesse Warden dot Kizz-ohm » Blog Archive » Good Memory Management When Using PureMVC — November, 3 2009 #

  34. [...] Using Object Pools [...]

    Pingback by Yi’s blog - ??fLEX????????? — November, 10 2009 #

  35. Memory Management in Flex and Flash…

    This page contains various resources about memory management in Flex and Flash. Table of contents Articles External resources General Unloading Flex Modules…

    Trackback by Confluence: Knowledge — November, 17 2009 #

  36. I can’t get this to compile in CS4. Think it’s to do with this bug: Cannot use Interface and internal class both in single AS file

    Move SimpleFactory to its own class and it’s ok again.

    Comment by Anthony — January, 19 2010 #

  37. Thank you. very useful ariticle!

    Comment by jidolstar — February, 22 2010 #

Leave a comment

XHTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Proudly powered by WordPress Theme based upon Pool theme by Borja Fernandez.
Entries and comments feeds.