いよいよ来週は CS5 発表のオンラインイベントですね。
Optimizing Performance for the Flash Platform から、AS3 関連の Tips です。この分野はいろいろな最適化手法がありますので、ここで紹介されているもの以外にも探せば見つかると思います。このページ Some ActionScript 3.0 Optimizations の下の方にもいろいろなサイトへのリンクがまとめられています。ご参考まで。
さて、本題に戻って、
Vector と Array
- 可能な場合は Vector を使用した方が早い
- 必要な Vector の大きさを最初に指定しておくとさらに早い (メモリ領域が足りなくなると、新たなメモリ確保とデータのコピーが必要になるため)
const MAX_NUM:int = 300000; var coordinates:Vector.<Number> = new Vector.<Number>(MAX_NUM, true);
描画 API
- Flash Player 10 から追加された新しい描画 API を使うと、従来の moveTo() や lineTo() を使った処理よりも高速化できる
drawPath()
drawGraphicsData() - 描画する図形が複雑になるほどその差が大きくなる
var container:Shape = new Shape(); container.graphics.beginFill(0x442299); var coords:Vector.<Number> = Vector.<Number>([132, 20, 46, 254, 244, 100, 20, 98, 218, 254]); var commands:Vector.<int> = Vector.<int>([1,2,2,2,2]); container.graphics.drawPath(commands, coords);
イベントの伝播
- 複数の子オブジェクトで同様のイベント処理が必要な場合、個々のオブジェクトでイベントを処理する代わりに、イベントフローを利用して、親オブジェクトでまとめてイベント処理をすると処理の負荷を軽減できる (呼び出すメソッドの数が 1 つで済む)
- 伝播の必要の無いイベントは、フローを中断させることで不要な処理を避けることができる
function onMouseEvent ( e:MouseEvent ):void { // イベントフローを止める e.stopPropagation(); // 必要な処理を個々に記述 }
ピクセルの操作
- Flash Player 10 から追加された setVector() を使うとピクセルに値の設定を高速に行うことができる
- setPixel() や setPixel32() を使う場合でも lock(), unlock() メソッドを使ったパフォーマンスの改善が可能
var myImage:BitmapData = new BitmapData(200,200,true,0xFFFFFFFF); var container:Bitmap = new Bitmap(myImage); // イメージデータをロック myImage.lock(); for (var i:int = 0; i<2000000; i++) { // イメージデータを更新 myImage.setPixel32( xx, yy, 0x66990000 ); } // ロックを解除、この時点で container に変更が反映される myImage.unlock();
- lock() を呼ぶと、unlock() が呼ばれるまでイメージデータへの変更が反映されない
- ピクセル値を読み込む場合も getPixel() よりは getVector() メソッドを使用した方が高速
- 特にモバイルでは差が出やすい
その他の最適化
- TextField オブジェクトを使うときは += オペレーターではなく appendText() メソッドを使う
- 複数回 appendText() を呼ぶよりは、String を += オペレーターで結合してから TextField.text 属性に設定した方が早い
- TextFiled の HTML テキスト処理は重いため、TextFiled.htmlText += "<p>new line</p>"; のようなコードをループ中に書くのは避ける
- [] オペレータの使用はできるだけ避ける。配列中の同じオブジェクトを複数回参照する場合は、いったんローカル変数に参照を渡してから使用する
- ループの評価に式を使用しない。例えば、for (var i:int = 0; i < myArray.length; i++) のように記述すると、毎回 myArray.length の評価が必要になってしまう
- while ループの場合は、while (--i > -1) のように減らす方向のほうが処理速度が速い
whileループでカウンタ変数を減算する方が速いという理由がわかりません。実際試したところでも、差は認められませんでした。
http://www.jagra.or.jp/schoolblog/2010/04/actionscript-30.html
while (++i < myArray.length)のような場合と比較している訳ではないですよね。
野中さん、コメントありがとうございます。
この記事は、元記事の紹介として書いています。
よろしければ、下のリンクにコメントしてくださいませ。
http://help.adobe.com/en_US/as3/mobile/WS4bebcd66a74275c3a0f5f19124318fc87b-7ffc.html
blogにテスト用のコードをアップロードしたうえで、ドキュメントにCommentを加えました。
http://blog.jactionscripters.com/2010/04/12/decrement-versus-increment-in-loop/
野中さん、ありがとうございました。
リリース版ドキュメントには反映されるとよいですね。