最近のトラックバック

スポンサード リンク


  • Google
    Web sketch.txt-nifty.com

リンク

« ActionScript日記 - サウンドのリアルタイム生成(4) | トップページ | ActionScript日記 - サウンドのリアルタイム生成(5) »

ActionScript日記 - 高速化

 FlMMLがどうにも重いので、高速化の手法について少し調べてみました。

 まず参考になったのが、ConquestArrowさんのこちらの記事
 forループの中でlength使ったときって、コンパイラで最適化してくれないんですねぇ。これは直さないと拙いな。
 配列の要素を読むときに型キャストをするというのも効果ありそうですね。

 もうひとつ参考にしたのがBeInteractive!さんの一連の記事。  なかでも気になったのが switch-caseの最適化という記事なんですけれども、例に挙がってるのは文字列switchの場合なんですよね。数値switchの場合でも同様に高速化できるのかな? 調べてみますか。
 ベンチマークのコードはこんな感じ。

Bench.as
package {
        import flash.display.*;
        
        public class Bench extends Sprite {
                private static const SIZE:int = 1000000;
                private static const FUNC:int = 10;
                private var arr:Array = new Array(SIZE);
                private var func:Array = new Array(FUNC);
                
                private function funcSwi():void {
                        var s:int = FUNC-1;
                        for(var i:int = 0; i < SIZE; i++) {
                                switch(s) {
                                        case 0: arr[i] = 0; break;
                                        case 1: arr[i] = 0; break;
                                        case 2: arr[i] = 0; break;
                                        case 3: arr[i] = 0; break;
                                        case 4: arr[i] = 0; break;
                                        case 5: arr[i] = 0; break;
                                        case 6: arr[i] = 0; break;
                                        case 7: arr[i] = 0; break;
                                        case 8: arr[i] = 0; break;
                                        case 9: arr[i] = 0; break;
                                }
                        }
                }
                
                private function testFunc(a:Array, i:int):void {
                        a[i] = 0;
                }
                
                private function funcTbl():void {
                        var s:int = FUNC-1;
                        for(var i:int = 0; i < SIZE; i++) {
                                func[s](arr, i);
                        }
                }
                
                public function Bench() {
                        for(var i:int = 0; i < FUNC; i++) func[i] = testFunc;
                        trace("FUNC:"+FUNC);
                        bench(funcSwi, "swi");
                        bench(funcTbl, "tbl");
                }
                
                public function bench(func:Function, str:String):void {
                        var starttime:Date = new Date();
                        func();
                        var endtime:Date = new Date();
                        trace(str + ": " + (endtime.getTime() - starttime.getTime()) + "msec.");
                }
        }
}

結果。
  switch-case:250msec.
  関数テーブル:601msec.
あれー? 普通にswitch-caseのほうが速いですね。caseを100個にしてみましょうか。
  switch-case:471msec.
  関数テーブル:681msec.
これでもswitch-caseのほうが速いみたいですね。FlMMLでは普通にswitch-caseでよさそうです。

 次に、これから多用するであろう sin関数と pow関数をテーブル引きに変えたら速くなるのかどうか見てみましょうか。

Bench.as
package {
        import flash.display.*;
        
        public class Bench extends Sprite {
                private static const SIZE:int = 1000000;
                private var siz:int = 1000000;
                private var arr:Array = new Array(SIZE);
                
                private function funcSin():void {
                        var p:Number = 0.0;
                        var d:Number = Math.PI / SIZE;
                        for(var i:int = 0; i < SIZE; i++) {
                                arr[i] = Math.sin(p);
                                p += d;
                        }
                }
                
                private function funcPow():void {
                        var p:Number = 0.0;
                        var d:Number = 1.0 / SIZE;
                        for(var i:int = 0; i < SIZE; i++) {
                                arr[i] = Math.pow(440, p);
                                p += d;
                        }
                }
                
                private function funcTbl():void {
                        var p:Number = 0.0;
                        var d:Number = 0.5;
                        for(var i:int = 0; i < SIZE; i++) {
                                arr[i] = arr[int(p)];
                                p += d;
                        }
                }
                
                public function Bench() {
                        bench(funcSin, "sin");
                        bench(funcPow, "pow");
                        bench(funcTbl, "tbl");
                }
                
                public function bench(func:Function, str:String):void {
                        var starttime:Date = new Date();
                        func();
                        var endtime:Date = new Date();
                        trace(str + ": " + (endtime.getTime() - starttime.getTime()) + "msec.");
                }
        }
}

結果。
  Math.sin:861msec.
  Math.pow:1923msec.
  テーブル引き:130msec.
ぎゃあ。全然違いますね。テーブル引きにしましょう。

最後に forループを回すときの書き方についても調べておきますか。

Bench.as
package {
        import flash.display.*;
        
        public class Bench extends Sprite {
                private static const SIZE:int = 1000000;
                private var mem:int = SIZE;
                private var arr:Array = new Array(SIZE);
                
                private function funcLen():void {
                        var p:Number = 0.0;
                        var d:Number = 0.5;
                        for(var i:int = 0; i < arr.length; i++) {
                                arr[i] = arr[int(p)];
                                p += d;
                        }
                }
                private function funcMem():void {
                        var p:Number = 0.0;
                        var d:Number = 0.5;
                        for(var i:int = 0; i < mem; i++) {
                                arr[i] = arr[int(p)];
                                p += d;
                        }
                }
                private function funcCon():void {
                        var p:Number = 0.0;
                        var d:Number = 0.5;
                        for(var i:int = 0; i < SIZE; i++) {
                                arr[i] = arr[int(p)];
                                p += d;
                        }
                }
                private function funcLcl():void {
                        var p:Number = 0.0;
                        var d:Number = 0.5;
                        var n:int = SIZE;
                        for(var i:int = 0; i < n; i++) {
                                arr[i] = arr[int(p)];
                                p += d;
                        }
                }
                
                public function Bench() {
                        bench(funcLen, "len");
                        bench(funcMem, "mem");
                        bench(funcCon, "con");
                        bench(funcLcl, "lcl");
                }
                
                public function bench(func:Function, str:String):void {
                        var starttime:Date = new Date();
                        func();
                        var endtime:Date = new Date();
                        trace(str + ": " + (endtime.getTime() - starttime.getTime()) + "msec.");
                }
        }
}


結果。
  配列のlengthを条件に:441msec.
  メンバ変数を条件に:140msec.
  static constを条件に:140msec.
  ローカル変数を条件に:131msec.
やっぱりローカル変数を条件にしてループをまわすのがいいみたいですね。

« ActionScript日記 - サウンドのリアルタイム生成(4) | トップページ | ActionScript日記 - サウンドのリアルタイム生成(5) »

ActionScript 3.0」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/5373/16546143

この記事へのトラックバック一覧です: ActionScript日記 - 高速化:

« ActionScript日記 - サウンドのリアルタイム生成(4) | トップページ | ActionScript日記 - サウンドのリアルタイム生成(5) »

ブログパーツ



2015年5月
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31            
無料ブログはココログ