今このタイミングでFlash9のArrayの挙動については100%誰も興味が無い.
id:keim_at_Si:20080523の続き.as3のArrayはかなり気持ち悪いので,自分のプログラムでも,ボトルネックになりそうなところではほとんど使ってません.Flash10のVector調べる前にArrayの気持ち悪さを再確認してみましょう.しかし,ほんとキモいなー,これ.
Array ベンチマーク for int
Array ベンチマーク for Number
少し止まったあと,各ループの処理時間が表示されます.環境依存激しそうなので皆さん自分の環境でやってみてください.プレイヤーが古いですがうちの1GHzノートの場合,
for int
デバッガの結果. Windows XP/StandAlone/WIN 9,0,115,0/debugger 862[ms] { array[i] += t1; } 846[ms] { array[i] = array[i] + t1; } 1047[ms] { array[i] = int(array[i]) + t1; } 494[ms] { t0 = array[i]; t0 += t1; array[i] = t0; } 491[ms] { t0 = array[i]; t0 = t0 + t1; array[i] = t0; } 583[ms] { t0 = array[i]; array[i] = t0 + t1; } 685[ms] { array[i] = array[i + t1]; } 417[ms] { t0 = i + t1; array[i] = array[t0]; }
ie上での結果. Windows XP/ActiveX/WIN 9,0,115,0/normal 695[ms] { array[i] += t1; } 698[ms] { array[i] = array[i] + t1; } 451[ms] { array[i] = int(array[i]) + t1; } 376[ms] { t0 = array[i]; t0 += t1; array[i] = t0; } 374[ms] { t0 = array[i]; t0 = t0 + t1; array[i] = t0; } 449[ms] { t0 = array[i]; array[i] = t0 + t1; } 529[ms] { array[i] = array[i + t1]; } 321[ms] { t0 = i + t1; array[i] = array[t0]; }
for Number
デバッガの結果. Windows XP/StandAlone/WIN 9,0,115,0/debugger 919[ms] { array[i] += t1; } 932[ms] { array[i] = array[i] + t1; } 1080[ms] { array[i] = Number(array[i]) + t1; } 604[ms] { t0 = array[i]; t0 += t1; array[i] = t0; } 613[ms] { t0 = array[i]; t0 = t0 + t1; array[i] = t0; } 644[ms] { t0 = array[i]; array[i] = t0 + t1; }
ie上での結果. Windows XP/ActiveX/WIN 9,0,115,0/normal 769[ms] { array[i] += t1; } 770[ms] { array[i] = array[i] + t1; } 502[ms] { array[i] = Number(array[i]) + t1; } 505[ms] { t0 = array[i]; t0 += t1; array[i] = t0; } 508[ms] { t0 = array[i]; t0 = t0 + t1; array[i] = t0; } 512[ms] { t0 = array[i]; array[i] = t0 + t1; }
4,5,6行目の高速化も十分気持ち悪いんだけど,特にArrayの異常さを感じたのは for int の7,8行目かな.だれかTamarinソースによる合理的な説明を求む.あと3行目のデバッガとブラウザでの速度差に震撼.キャストしておくとJITコンパイラで最適化されるよって話を,たしかAdobeのプレゼン資料で読んだ気はしてたんだけど,デバッガ上では最適化されてないみたい.うわー.
とりあえずArrayは計算式内で直接使わずローカル変数に代入して使う.あとインデックスもあらかじめ計算しておく.
結論,Arrayきもい.
以下ソース
for int.
package { import flash.text.TextField; import flash.display.*; import flash.utils.getTimer; import flash.system.Capabilities; [SWF(width="640", height="480", backgroundColor='#ffffff')] public class main extends Sprite { function main() { var i:int, imax:int = 4999999; var time:int, array:Array = new Array(imax); var res:String = Capabilities.os+"/"; res += Capabilities.playerType+"/"; res += Capabilities.version+"/"; res += (Capabilities.isDebugger?"debugger":"normal")+"\n"; //----test start var t0:int, t1:int; for (i=0; i<imax; i++) { array[i] = int(0); } imax--; t1 = 1; time = getTimer(); for (i=0; i<imax; i++) { array[i] += t1; } res += String(getTimer() - time) + '[ms] { array[i] += t1; }\n'; time = getTimer(); for (i=0; i<imax; i++) { array[i] = array[i] + t1; } res += String(getTimer() - time) + '[ms] { array[i] = array[i] + t1; }\n'; time = getTimer(); for (i=0; i<imax; i++) { array[i] = int(array[i]) + t1; } res += String(getTimer() - time) + '[ms] { array[i] = int(array[i]) + t1; }\n'; time = getTimer(); for (i=0; i<imax; i++) { t0 = array[i]; t0 += t1; array[i] = t0; } res += String(getTimer() - time) + '[ms] { t0 = array[i]; t0 += t1; array[i] = t0; }\n'; time = getTimer(); for (i=0; i<imax; i++) { t0 = array[i]; t0 = t0 + t1; array[i] = t0; } res += String(getTimer() - time) + '[ms] { t0 = array[i]; t0 = t0 + t1; array[i] = t0; }\n'; time = getTimer(); for (i=0; i<imax; i++) { t0 = array[i]; array[i] = t0 + t1; } res += String(getTimer() - time) + '[ms] { t0 = array[i]; array[i] = t0 + t1; }\n'; time = getTimer(); for (i=0; i<imax; i++) { array[i] = array[i + t1]; } res += String(getTimer() - time) + '[ms] { array[i] = array[i + t1]; }\n'; time = getTimer(); for (i=0; i<imax; i++) { t0 = i + t1; array[i] = array[t0]; } res += String(getTimer() - time) + '[ms] { t0 = i + t1; array[i] = array[t0]; }\n'; //----test end var tf:TextField = new TextField(); tf.multiline = true; tf.width = 640; tf.height = 480; tf.selectable = true; tf.textColor = 0x000000; tf.text = res; addChild(tf); stage.scaleMode = StageScaleMode.NO_SCALE; } } }
for Number.
//----test start var t0:Number, t1:Number; for (i=0; i<imax; i++) { array[i] = Number(0); } imax--; t1 = 1; time = getTimer(); for (i=0; i<imax; i++) { array[i] += t1; } res += String(getTimer() - time) + '[ms] { array[i] += t1; }\n'; time = getTimer(); for (i=0; i<imax; i++) { array[i] = array[i] + t1; } res += String(getTimer() - time) + '[ms] { array[i] = array[i] + t1; }\n'; time = getTimer(); for (i=0; i<imax; i++) { array[i] = Number(array[i]) + t1; } res += String(getTimer() - time) + '[ms] { array[i] = Number(array[i]) + t1; }\n'; time = getTimer(); for (i=0; i<imax; i++) { t0 = array[i]; t0 += t1; array[i] = t0; } res += String(getTimer() - time) + '[ms] { t0 = array[i]; t0 += t1; array[i] = t0; }\n'; time = getTimer(); for (i=0; i<imax; i++) { t0 = array[i]; t0 = t0 + t1; array[i] = t0; } res += String(getTimer() - time) + '[ms] { t0 = array[i]; t0 = t0 + t1; array[i] = t0; }\n'; time = getTimer(); for (i=0; i<imax; i++) { t0 = array[i]; array[i] = t0 + t1; } res += String(getTimer() - time) + '[ms] { t0 = array[i]; array[i] = t0 + t1; }\n'; //----test end