可能な場合は、オブジェクトプーリングを使用してください。
重要な最適化の一つに、オブジェクトプーリングと呼ばれる手法があります。この手法では、長い期間にわたってオブジェクトを再利用します。アプリケーションの初期化時に、限られた数のオブジェクトを作成し、プール内に Array オブジェクトや Vector オブジェクトなどとして格納します。オブジェクトを格納したら、それらを無効化して CPU リソースを消費しないようにします。また、相互参照はすべて削除します。ただし、参照を
null
に設定しないでください。これを行うと、ガベージコレクションの対象となる可能性があります。オブジェクトをプールに戻し、新しいオブジェクトが必要になったときに、そのオブジェクトを取得します。
オブジェクトを再利用すると、オブジェクトをインスタンス化する必要が減ります。オブジェクトのインスタンス化には費用が掛かります。また、アプリケーションの動作速度を低下させる可能性のあるガベージコレクターの実行回数も削減されます。次のコードは、オブジェクトプーリング手法を示しています。
package
{
import flash.display.Sprite;
public final class SpritePool
{
private static var MAX_VALUE:uint;
private static var GROWTH_VALUE:uint;
private static var counter:uint;
private static var pool:Vector.<Sprite>;
private static var currentSprite:Sprite;
public static function initialize( maxPoolSize:uint, growthValue:uint ):void
{
MAX_VALUE = maxPoolSize;
GROWTH_VALUE = growthValue;
counter = maxPoolSize;
var i:uint = maxPoolSize;
pool = new Vector.<Sprite>(MAX_VALUE);
while( --i > -1 )
pool[i] = new Sprite();
}
public static function getSprite():Sprite
{
if ( counter > 0 )
return currentSprite = pool[--counter];
var i:uint = GROWTH_VALUE;
while( --i > -1 )
pool.unshift ( new Sprite() );
counter = GROWTH_VALUE;
return getSprite();
}
public static function disposeSprite(disposedSprite:Sprite):void
{
pool[counter++] = disposedSprite;
}
}
}
アプリケーションの初期化時に、SpritePool クラスが新しいオブジェクトのプールを作成します。
getSprite()
メソッドでこれらのオブジェクトのインスタンスを返し、
disposeSprite()
メソッドでインスタンスを解放します。このコードでは、プールを使い切ったときにプールを拡大することができます。固定サイズのプールを作成することも可能です。この場合は、プールを使い切ると新しいオブジェクトを割り当てられなくなります。可能な場合は、ループ内での新しいオブジェクトの作成は避けてください。詳しくは、
メモリの解放
を参照してください。次のコードでは、SpritePool クラスを使用して、新しいインスタンスを取得します。
const MAX_SPRITES:uint = 100;
const GROWTH_VALUE:uint = MAX_SPRITES >> 1;
const MAX_NUM:uint = 10;
SpritePool.initialize ( MAX_SPRITES, GROWTH_VALUE );
var currentSprite:Sprite;
var container:Sprite = SpritePool.getSprite();
addChild ( container );
for ( var i:int = 0; i< MAX_NUM; i++ )
{
for ( var j:int = 0; j< MAX_NUM; j++ )
{
currentSprite = SpritePool.getSprite();
currentSprite.graphics.beginFill ( 0x990000 );
currentSprite.graphics.drawCircle ( 10, 10, 10 );
currentSprite.x = j * (currentSprite.width + 5);
currentSprite.y = i * (currentSprite.width + 5);
container.addChild ( currentSprite );
}
}
次のコードでは、マウスをクリックしたときに、表示リストからすべての表示オブジェクトが削除されます。削除された表示オブジェクトは後で別のタスクに再利用します。
stage.addEventListener ( MouseEvent.CLICK, removeDots );
function removeDots ( e:MouseEvent ):void
{
while (container.numChildren > 0 )
SpritePool.disposeSprite (container.removeChildAt(0) as Sprite );
}
注意:
プール内の Vector オブジェクトは常に Sprite オブジェクトを参照します。オブジェクトをメモリから完全に削除する場合は、SpritePool クラスの
dispose()
メソッドが必要です。このメソッドは、残っているすべての参照を削除します。