Home >
In my previous article I detailed the architecture for a video player that would switch between multiple players, using composition to support the same interface across each layer of the architecture.
The architecture worked out really well, but when I profiled the actual implementation I found there was an issue with memory management. The general idea is that the PlayerSwapper object would instantiate a new version of the appropriate wrapper object and set that to it's player variable.
The problem was some of those players were external SWFs, and once loaded in, the Flash player wasn't releasing them. As I profiled the application there was a steady increase in memory allocated as each video was played and a new player was instantiated.
To solve this I changed the functionality of the PlayerSwapper class a little.
I had the PlayerSwapper object keep a Dictionary of players - the Dictionary object is an associative array that keeps an object as the index. I created an Enumerator to list all potential player types for reference, and used each Enum value as the Dictionary index and the player instance as the value at that index.
In such a way I was able to check if a player was already instantiated - and if it was use it, but if it wasn't, to create it and store it in the Dictionary for future use as well. This allowed me to slowly build to a memory plateau that never grew beyond the size needed for all players. In fact since it only instantiated a player that it needed, depending on the play list, some players were never instantiated.
private var _client:ClientEnum;
private var _vo:VideoObject
private var _playerDictionary:Dictionary
public function PlayerSwapper(w:Number=320, h:Number=240, x:Number=0, y:Number=0)
{
_playerDictionary = new Dictionary(true);
}
private function createPlayers(c:ClientEnum):void
{
var tempPlayer:IPlayer
switch(c.value)
{
case ClientEnum.A:
tempPlayer = new PlayerAWrapper(this._vidW, this._vidH, this.x, this.y);
break
case ClientEnum.B:
tempPlayer = new PlayerBWrapper(this._vidW, this._vidH, this.x, this.y)
break;
case ClientEnum.C:
tempPlayer = new PlayerCWrapper(this._vidW, this._vidH, this.x, this.y)
break;
case ClientEnum.D:
tempPlayer = new PlayerDWrapper(this._vidW, this._vidH, this.x, this.y)
break;
}
if(!_playerDictionary[c]) _playerDictionary[c] = tempPlayer
}
public function getPlayer():IPlayer
{
var tempPlayer:IPlayer
if(_vo.client != null && _vo.releaseUrl != null)
{
tempPlayer = null
if(!_playerDictionary[this.client]) createPlayers(this.client)
tempPlayer = _playerDictionary[this.client]
}
return tempPlayer;
}
public function attachPlayer():void
{
_player = getPlayer()
addChild(_player as Sprite)
_player.source = source;
}




Facebook Application Development
Pooling objects like this might be a good idea, but if the issue is really with wanting to free memory used by loaded-in SWFs, have you tried using Loader.unloadAndStop()?
This method (new in FP10) should make a loaded SWF (the one loaded by the Loader on which the method is executed) eligible for garbage collection, provided you haven't applied any event listeners, or in any other way stored a reference to it, or any of it's children, et c..
Im completeley out of the loop regarding flash and actionscript. might use some of the code here for my project ideenmanagement24 tho. cheers.
@Richard - I'm familiar with unloadAndStop but my audience is still using 9.x player, so I can't reliably use player 10 features yet for something so essential. The lowest version that I have to support is 9.0.28 - which is used by less than a percentage of my audience but still constitutes hundreds of thousands of users.
When using object caching, you create a cache of objects that the application can use. When the application is finished with these objects, you return the objects to the cache so that they can be reused again. This technique reduces the number of object instances created by the runtime, reduces the overall memory used when running the application, stabilizes the required resources to run the application and leads to better overall performance and scalability of the application when applied correctly.