ActionScript 3
パフォーマンスの最適化
サーチ…
ベクトルベースのグラフィックス
ベクトルベースのグラフィックスは、CPUによって計算されなければならない膨大なデータ(ベクトル点、アーク、色など)によって表されます。最小限の点と直線を持つ単純な形状以外のものは、膨大なCPUリソースを消費します。
オンにできる「ビットマップとしてのキャッシュ」フラグがあります。このフラグは、はるかに高速な再描画のためにベクターベースのDisplayObjectを描画した結果を格納します。この落とし穴は、オブジェクトに適用された変換があれば、全体を再描画して再キャッシュする必要があるということです。フレームごとの変換(回転、スケーリングなど)が適用されている場合は、これをまったくオンにしないよりも遅くなる可能性があります。
一般に、ビットマップを使用したグラフィックスのレンダリングは、ベクトルグラフィックスを使用する場合よりもはるかに効率的です。 flixelなどのライブラリは、フレームレートを低下させることなくスプライトを「キャンバス」にレンダリングするためにこれを利用します。
テキスト
レンダリングテキストは、多くのCPUを消費します。フォントは、ベクターグラフィックスと同様の方法でレンダリングされ、すべての文字に対して多くのベクトル点を含みます。テキストをフレーム単位で変更すると 、パフォーマンスが低下します。 "キャッシュとしてのビットマップ"フラグは、正しく使用すると非常に便利です。つまり、回避する必要があります。
- テキストを頻繁に変更する。
- テキストフィールドの変換(回転、スケーリング)。
if
ステートメントでテキストの更新をラップするなどの単純な手法は大きな違いをもたらします:
if (currentScore !== oldScore) {
field.text = currentScore;
}
テキストは、Flashに組み込まれたアンチエイリアスレンダラを使用して、または「デバイスフォント」を使用してレンダリングできます。 「デバイスフォント」を使用すると、テキストがギザギザ(エイリアス)に見えますが、テキストのレンダリングがはるかに高速になります。また、デバイスフォントでは、エンドユーザーがフォントをあらかじめインストールしておく必要があります。または、ユーザーのPC上でテキストが「消えて」いるかもしれませんが、あなたの上には問題はありません。
field.embedFonts = false; // uses "device fonts"
Vectorと各vs配列、およびfor
Vector.<T>
型とfor each
ループのfor each
を使用すると、従来の配列とfor
ループよりもパフォーマンスが向上for
ます。
良い:
var list:Vector.<Sprite> = new <Sprite>[];
for each(var sprite:Sprite in list) {
sprite.x += 1;
}
悪い:
var list:Array = [];
for (var i:int = 0; i < list.length; i++) {
var sprite:Sprite = list[i];
sprite.x += 1;
}
高速配列アイテムの削除
特定の順序で配列を必要としない場合は、 pop()
すると、 splice()
比べて大きなパフォーマンス向上が得られます。
配列をsplice()
するとき、その配列内の後続の要素のインデックスを1つ減らす必要があります。このプロセスは、配列が大きく、削除するオブジェクトがその配列の先頭に近い場合に、大きな時間を費やす可能性があります。
配列内の要素の順序を気にしない場合は、削除する項目を、配列の最後からpop()
する項目に置き換えることができます。この方法では、配列内の他のすべての項目のインデックスは変わりません。配列の長さが長くなるにつれて、処理が低下することはありません。
例:
function slowRemove(list:Array, item:*):void {
var index:int = list.indexOf(item);
if (index >= 0) list.splice(index, 1);
}
function fastRemove(list:Array, item:*):void {
var index:int = list.indexOf(item);
if (index >= 0) {
if (index === list.length - 1) list.pop();
else {
// Replace item to delete with last item.
list[index] = list.pop();
}
}
}
配列の代わりにベクトル
Flash Player 10では、Arrayよりも高速なVector。* genericリストタイプが導入されました。しかし、これは完全に真実ではありません。次のVectorタイプのみが、Flash Playerで実装されているため、Arrayクラスよりも高速です。
-
Vector.<int>
- 32ビット整数のベクトル -
Vector.<uint>
- 32ビット符号なし整数のベクトル -
Vector.<Double>
- 64ビット浮動小数点のベクトル
それ以外の場合は、すべての操作(作成、操作など)に対して、配列を使用する方がベクトルを使用するよりもパフォーマンスが向上します。ただし、コードを「強く入力する」場合は、減速にもかかわらずベクターを使用できます。 FlashDevelopには、 /*ObjectType*/Array
を使用して、配列の場合でもコード補完ドロップダウンが機能するような構文があります。
var wheels:Vector.<Wheel> // strongly typed, but slow
var wheels:/*Wheel*/Array // weakly typed, but faster
グラフィックの再利用とプール
実行時にSprite
オブジェクトとTextField
オブジェクトを作成して設定すると、1つのフレームに数十万ものオブジェクトを作成する場合、コストがかかる可能性があります。したがって、共通のトリックは、後で再利用するためにこれらのオブジェクトを「プールする」ことです。作成時間( new Sprite()
)だけでなく、設定(デフォルトプロパティの設定)も最適化しようとしていることに注意してください。
何百ものTextFieldオブジェクトを使用してリストコンポーネントを構築していたとしましょう。新しいオブジェクトを作成する必要がある場合は、既存のオブジェクトを再利用できるかどうかを確認します。
var pool:Array = [];
if (pool.length > 0){
// reuse an existing TextField
var label = pool.pop();
}else{
// create a new TextField
label = new TextField();
// initialize your TextField over here
label.setDefaultTextFormat(...);
label.multiline = false;
label.selectable = false;
}
// add the TextField into the holder so it appears on-screen
// you will need to layout it and set its "text" and other stuff seperately
holder.addChild(label);
後で、コンポーネントを破棄(または画面から削除)するときは、未使用のラベルをプールに戻すようにしてください。
foreach (var label in allLabels){
label.parent.removeChild(label); // remove from parent Sprite
pool.push(label); // add to pool
}
ほとんどの場合、グローバルプールの代わりに1つのプールを作成することをお勧めします。グローバルプールを作成する際の短所は、毎回オブジェクトをプールから取得するためにオブジェクトを再初期化し、他の関数によって行われた設定を無効にする必要があることです。これは同じくらいコストがかかり、最初にプールを使用することによるパフォーマンスの向上を否定します。