Flash 10.1になって遅くなった部分と速くなった部分

現在、Flash Player 10.1 は RC4 で、すでに Google Chrome 5 βでは標準搭載になっています。

Flash 10.1 はスマートフォン対応がメインで、パソコン版は大差ないのですが、パフォーマンス面で変更が加えられています。遅くなった部分と、速くなった部分があり、ひょっとしたら、ゲーム系は大旨fpsが落ちるかもしれません。

遅くなった部分(タイマー)

最大の変更点は、タイマーの仕様の変更です。互換性のない変更です。Adobeの人が、http://www.kaourantin.net/2010/03/timing-it-right.html, http://www.kaourantin.net/2010/04/press-any-key-to-continue.htmlにまとめています。

ブラウザ間の差を吸収するため、内部で 60Hz のタイマーを持つことにしたそうです。ビデオ以外の全ての処理が、この60Hzに合わせて処理されます。setTimeout(func, 5) などとやった場合、5ms 後に動いて欲しいのですが、60Hz に合わせないといけないので、最長 21.6ms(5ms + 16.6ms) 後になります。Flash Player 10.0 では、setTimeout(func, 0) とやった場合、1ms 以下で反応してくれたのですが、これも、16.6ms になります。Timer クラスなども当然これに従います。

I/O やローカルの通信もこれに従い、swf 間のローカル通信は、最低33ms、実測は40ms以上かかるようになったそうです。ExternalInterface もこのタイマーに従っているはずです。

結果として、ゲームなどで、Timer を使って、フレームごとの処理をしているアプリは、いままでは、可能な限り、最速で次のフレームに進めてくれたのが、60Hz にそろってしまうため、待ち時間が長くなってしまいます。もし、フレームの処理時間が一定ならば、60fps -> 30fps -> 20fps -> 15fps という形で落ちていきます。

ちなみに、JavaScript では、Google Chrome が setTimeout() の最小時間は 4ms で、それ以外のブラウザは10msです。(詳細は、setIntervalとsetTimeoutを調べた結果余分なことになった - 三等兵。でも、これは、Windows 7の話であり、XPだと違う結果になるようですし、MacOSX も違うらしいです。Test JS setTimeout() speedで計測できます。)。Flash 10.1ではこれが、16.6ms になります。

また、気をつけないといけないのが、10.1 から60Hzのタイマーが、非表示のFlashの場合、音を再生していない場合は2Hz、再生している場合は8Hzに落とすようにしたそうです。CPUパワーの節約が目的です。「非表示」の定義は、バックグラウンドのタブだったり、スクロールで非表示になったりなどですが、全てのブラウザで正確に非表示かどうか判定できるわけではなく、詳細は http://www.kaourantin.net/2010/04/press-any-key-to-continue.html をご覧ください。この機能をアプリ側で無効にするオプションってないのでしょうか?非表示になっても、60Hzで動いて欲しい時もあります。

遅くなった部分(例外)

Global Error Handling が追加になった副作用なのかはわかりませんが、例外の throw catch が遅くなっています。物凄く単純なテストで、2倍遅くなっています。スタックの保存がたくさんある場合は、未テストです。ごめんなさい。

速くなった部分

速くなった部分もたくさんあります。僕が見つけた範囲では、以下の通りです。

  • String.length が String の入っている変数に型がない場合で6倍速、型がある場合で8倍速。
  • 連想配列(Object)の読み書きが2倍速
  • ArrayやVectorの高速化により、挿入ソートのベンチマークは約10%速くなりました