Object Pooling in AS3

If you’re looking to save memory overhead and increase performance in your Flash creations then implementing the design pattern of Object Pooling is a great place to start. Object Pooling is most beneficial when the cost of construction is high or the frequency of construction is high.

Though it has to be known Object Pooling is not a silver bullet. There are definitely pitfalls to Object Pooling this most of all includes cleaning the Object for reuse. I’ll get back to this in just a moment but first I have to talk about Object Pools generally.

In short an Object Pool allows you to retrieve an instance of a particular type of Object by checking it in and out of a resource pool. The concept of checking in and out resources is very consistent when using an Object Pool. Though handling the situation when a pool is empty is not.

There are three approaches I will talk about when handling an empty pool :
1) The Unbounded Pool
The pool has a boundless size and Objects are added as required to the resource pool on check out. This ensures that an Object will always be returned on check out.

2) The Capped Pool
The pool has a constant size and the resource pool is populated during the construction of the pool. This allows you to have all the memory overhead in the pool construction and not during check out. Though when check outs occur to an empty pool it won’t return an Object.

3) The Queue Pool
The pool has a minimum size and the resource pool is populated during construction like option 1 it has the benefit of a maximum size – allowing the pool to grow. Unlike option 2 when the pool’s maximum size or flood limit is reached and a check out occurs on an empty pool then this request is queued. Requests in the queue will be eventually dropped if not fulfilled within a defined timeout or alternatively resolved once an Object is checked in. This doesn’t guarantee that the check out will be fulfilled by the Object Pool but does ensure that pools don’t grow uncontrollably and when they reach flood limits that the next fulfilled check out should be the last.

Each of these approaches to controlling the resource pool size have unique benefits and the option you choose depends on how size matters :). Lets say in one scenario that Object memory allocation is inexpensive and having 1,000’s to even 10,000’s of Objects is no big deal then option 1 is a good choice. Especially considering it’s simple and reliable. Though in another scenario where the same number of Objects are checked in as out and as a safe guard when a checkout occurs on an empty pool it can be suppressed then option 2 is a good choice. And doubly so considering a lot of the memory overhead of Object construction is on the Object Pool constructor and the pool will never grow out of your control. Though lastly if you can’t suppress check outs on empty pools and the next Object checkout should be the last one and you need to limit your pool size due to the Objects being expensive then option 3 is more than likely the best approach for you.

Now I’ll get back to Object cleaning, this sets an Object to the state it was in after construction which is important because check out is a replacement for constructing anew. The scenario when dirty Objects are added into the resource pool is often known as a cesspool and is considered an anti-pattern but honestly it’s up to you to wether this worries you or not. Though in regard to Object cleaning it’s also important to note this is where a clear pitfall emerges. If the process of cleaning is more expensive than construction then you should really consider not using an Object Pool.

If Object cleaning is important to you it gets interesting when consider the time and place to do this in your Object Pool class. It would seem logical to clean the Object within the check in method to ensure a cesspool never occurs. Though this could limit the Object Pool to containing a specific type of Object. This is because cleaning an Object is almost always subjective to type i.e. cleaning a DisplayObject is different to cleaning a BitmapData. Then thinking about this problem further the solution is “be kind rewind” – so the checkinee must clean before checkin. Problem solved.

And with every problem tackled there is another to solve. Creating an Object is also subjective to type due to parameters it may require in construction 🙁 Unfortunately there isn’t as ideal way to construct a Class with a dynamic number of parameters in Actionscript like function.apply offers for Functions. The simplest and most effective solution to this is once again the create process is external also. Another problem solved – hopefully that’s all 🙂

So now that’s enough talk on Object Pool’s and hopefully it’s given you some points to consider when creating your own Object Pool class. There’s an example below demonstrating the Object Pool concepts I’ve used and discussed above and has a small performance victory. What this example demonstrates is the performance cost in reinitializing the particle effect constantly. As you will see there is quite a noticeable difference between pooling or not but when you compare one pool concept over another there’s not much difference other than size handling features they offer which could save you performance.

If you would like to download the source code used in this example you can do so here.

AS3 SWF Profiler

This handy script applies a profiler option to the right click Flash Context Menu which allows you to debug or track the current FPS or memory used by your SWF. Further to this it also stores a configurable history length of the frame rate and memory performance for the SWF.

Adding this feature into your SWF couldn’t be easier than this line of code SWFProfiler.init(stage, this); and adding an import to the class you can download it here.

Tips on how to write efficient AS3

Just recently I have needed an in depth understanding of AS3 efficiency practises, so I figured this is easiest done by getting involved in a series of relevant tests. Though there are similar blog posts regarding this most have been focused on either loops or Number types and this article won’t repeat these tests as I too discovered similar suggestions.

Here are my tests :

Array & Object constructing

new Array() and new Object() are about 3 times slower than [] and {}. Though further to this [] is much slower than [].concat() so if you have a constant reference to an empty Array use [].concat().

Index Number type for Arrays

In AS2 list[int(0)] was faster than list[0] this is no longer the true. list[0] is now the faster option. list[int(0)] is now faster than list[0]!

Create Array vs. Updating Array

If you can avoid it don’t constantly create Arrays/Objects this is especially the case in long loops rather create them once then update.

Nulling Array vs. Splicing Array

When working with large Arrays splicing is obviously an expensive operation, you can avoid this by nulling the index and skipping it in a null scenario. If you need to splice in order to keep the Array length low. Then store these nulled indexes in another trash Array once the garbage count has reached a limit you’ve defined loop through the numerically sorted trash indexes deleting splices in bulk. This concept is demonstrated in Tweensy.

Nulling Object vs. Delete Object

Deleting an item in an Object is always more extensive than nulling it. If you’re using a Dictionary try to use weak references in that case once the key is dereferenced the Flash garbage collector will eventually remove the item from the Dictionary.

Nesting Loops

Nesting loops is always slower try to minimize your nest depth to no more than 2. As well always use for loops if you can they are the fastest.

Inline code vs. function references

When executing a function it’s more expensive if you call other functions within it, so if the function is an enterframe function or long loop try to minimize referencing alot of functions for best performance.

Arguments vs. variable referencing

Arguments in functions are slower than a reference to an objects variables so try to minimize the number of arguments you use.

Function apply scoping do it or not?

Scoping function.apply is a little bit slower than not so if you don’t have to then don’t.

AS3 Tween Engine – Tweensy (Preview)

Dynamic tweening is really important to a Flash Developer, and when I was programming in AS2 my tweening library of choice was either FuseKit or the Zigo Engine. Since AS3 there have been a few options available:

 

  • Tweener
  • Tween Lite
  • Adobe’s Tween
  • GTween
  • ASAP Tween

 

There have been many posts on how some are better in performance and features than others. Without going into detail, I rate them in the following order, from best to worst:
1) TweenLite/Max
2) Tweener
3) GTween
4) ASAP Tween
5) Adobe Tween

Even though there are 5 options above, the top 2 are the only ones I’d ever consider using. Even with this said, Tween Lite is good, but it’s not a code library I’d prefer to use. If anyone cares to take a look through the source code, they’ll notice that it’s not particularly clearly (well) written. Because of this, it’s not exactly easy for a developer to extend Tween Lite/Max if they need to.

Introducing Tweensy, my new tweening engine, which has been in use for the last 8 months on many of my commercial projects, which I’ll supply to the community free of charge (although donations are appreciated). As I mentioned above, Tween Lite/Max and Tweener are really the only libraries I feel I need to compare my performance and feature benchmarking with, to prove that Tweensy will equal, or more usually surpass the performance and features of the existing options. I’ll post these performance/feature comparison tests in my next post.

More importantly than this, I think it’s crucial that a new tweening engine should have its own unique point of difference. From my review of the above tweening engines, it is clear that they are built for a similar concept (property and motion tweening) and in a simplistic comparison they offer the same features with varying performance.

Tweensy, however, offers these unique features:

1) A Bitmap rendering feature allowing for Bitmap Effects not easily achieved from the Adobe filter set such as Directional Motion Blur, Liquid Theshold, Directional Displacement and Buldge/Skew Displacement.
2) Particle Emitters to generate smoke, fire, abstract, and magical effects from your motion tweens.
3) Vector shape Tweening
4) Gradient Tweening

Well enough of the introduction – I’ll show you some examples of what I’ve been able to achieve by utilizing some of the features above. I recommend that you install the Flash Player 10 beta to get the best FPS results.

 

So Tweensy is intended to provide motion effects, but at its core is an extremely efficient property tweening engine. As the name suggests, Tweensy is also designed to be very easy and flexible to use, so here’s the code of how I created the fire effect example above.

import com.flashdynamix.effects.layers.DisplacementLayer;
import com.flashdynamix.effects.*;
import com.flashdynamix.effects.extras.Emittor;

import flash.display.*;
import flash.geom.ColorTransform;
import flash.utils.getDefinitionByName;

var tween:Tweensy = new Tweensy();
var layer:DisplacementLayer = new DisplacementLayer(tween, 550, 400, 2, 2, BlendMode.NORMAL, 0.95, 1, -6, 1);

// This makes the layer offset each of the colour channels on each render so the result is black smoke
layer.ct.redOffset = -20;
layer.ct.blueOffset = -20;
layer.ct.greenOffset = -20;

// This is the start colour for the fire
var ct:ColorTransform = new ColorTransform(0, 0, 0, 1, 80, 30, 15);

// This is the display asset which will be used to render the flame effect
var Flame: Class = getDefinitionByName("Flame") as Class;

var emittor:Emittor = new Emittor(tween, Flame, BlendMode.ADD, 2, 0.73, 0.77, 5, 60, 0.5, -45, 90);
emittor.startColor = ct;
emittor.startScale = 0.2;
emittor.endScale = 2;

addChild(layer);

Now before someone comments, I do realise that this isn’t exactly 1 line of code. This is intentional because Tweensy is designed not only for the examples I demonstrate (examples are just to show what can be done), but provides a library with which you can create your own motion effects. This makes Tweensy a lot of fun to experiment with.

The source code to Tweensy is currently available as a public beta here. I am particularly interested in Flash developers who would like to get involved in creating their own motion effects examples to provide feedback and improve Tweensy. I hope to have a release version of Tweensy publicly available some in late October 2008 with a public beta available before then.

 

Camera Class Quirks with FMS

I did a project recently requiring a web camera recording to Flash Media Server 3. Whilst I was working on this I found out some interesting (annoying) things about the Camera class. These include :

Tip 1.

When initiating a connection to the Camera it’s best to do this through the Microphone class. Sounds odd I know! The reason for this is when this code is called :

var camera:Camera = Camera.getCamera();
ns.attachCamera(camera);

there’s a hang just after the allow button is selected on the security dialog panel. This is rationalled in the Adobe Flash help as ‘Scanning the hardware for cameras takes time’. So it’s best to trigger the security panel via

var microphone:Microphone = Microphone.getMicrophone();
ns.attachAudio(microphone);

then listen for the Status Event of UnMuted or later in your application call

var camera:Camera = Camera.getCamera();
ns.attachCamera(camera);

There will always be a delay on this code ns.attachCamera(camera); but at least via activating the Microphone first you won’t get a bug like delay of the security panel not disappearing immediately after the allow button is pressed.

Tip 2.

When recording to a Flash Media Server make sure the camera has activity via the Activity Status Event before publishing the stream. Otherwise you may get a static or black frame at the beginning of the recorded stream.

Tip 3.

To disable/turn off the Camera after a recording is complete do so via :

ns.attachCamera(null);

Though this is actually documented for AS3 it wasn’t in AS2. Once this has been done the Camera will need to be reconnected for a new recording and users will experience this delay again as the Camera starts as mentioned above.

Tip 4.

When embedding your Flash do not change the wmode from default. Otherwise you will get problems on specific browser configurations i.e. Firefox PC . These problems include that the allow button on the security dialog box will not hide on click.

Tip 5.

When detecting wether the user has a web camera you can’t rely on Camera.names.length(). This is because there are scenarios whereby devices will appear in the list which may not be webcameras but devices like TV capture cards and can not be used as a camera. The solution for this is when the camera is attached via

var camera:Camera = Camera.getCamera();
ns.attachCamera(camera);

Then add a time out catch which can be cleared via the camera’s activity event, so that if camera activity occurs within the time out of say 5 seconds then clear the timeout. Otherwise if the timeout happens handle the error scenario.

Tip 6.

Further to the above it’s good at the point of displaying the error message to give the user an option to fix this problem. This is because it may simply be a matter of the user changing the default camera selected. This can be done via adding a button and firing the Camera devices security dialog by the following :

Security.showSettings(SecurityPanel.CAMERA);

It’s interesting to know that when the user is selecting options from the Camera devices list it’s possible to detect wether the option selected is actually a Camera. Once again this is done via camera.activityLevel>0 on the Camera’s activity event. Sadly there is not yet a reliable way to detect when the dialog panel close event occurs. So with this in mind when the user has picked a camera, you should make a noticible visual change somewhere behind the dialog box (and overlay screen) so the user will proceed to the close button – happy days.

You Tube Flash AS3 / AS2 API

Recently I have been working on something involving the use of video content from You Tube. With the lack of a good API out there I created my own. Below is a simple example of this working with sample code to download further below.

AS3 Example

Actionscript:
import com.FlashDynamix.services.YouTube;
import com.FlashDynamix.events.YouTubeEvent;
//
var yt:YouTube = new YouTube();
yt.APIKey = "WplekwLy_Nw";
function onLoaded(e:YouTubeEvent) {
switch (e.method) {
case YouTube.VIDEOSBYTAG :
try {
for each (var video:XML in data) {
trace(video.name() + " : " + video);
}
trace("Videos For Tag : " + e.request.tag + " : " + e.data.length());
} catch (evt:ArgumentError) {
trace("ERROR : No Videos For Tag");
}
}
}
//
yt.addEventListener(YouTubeEvent.COMPLETE, onLoaded);
yt.videosbyTag("Top Gear");

AS2 example

Actionscript:
import com.FlashDynamix.services.YouTube;
//
var yt:YouTube = new YouTube();
yt.APIKey = "WplekwLy_Nw";
var obj:Object = new Object();
obj.loaded = function(evt:EventArgs) {
switch (evt.type) {
case YouTube.VIDEOSBYTAG :
var videos = evt.value.video;
break;
}
};
//
yt.addListeners(obj);
yt.videosbyTag("Top Gear");

The class I created YouTube.as supports all the features listed on the YouTube API documentation here http://www.youtube.com/dev_docs

Download the source here