- 2009年4月21日 02:09
- ActionScript 3.0
先日、アクセスログを見たのですが、様々な方がこのブログを見てくれているようで
チューニング情報くらいしかない、地味なブロガーとしては非常に嬉しく思っとります。
ありがとうございます。
そしてまた飽きもせずチューニング話です。
今まではプログラム的なものが多かったので
たまには、描画速度やらを検証してみたので公開します。
そして今回は何気にニーズが多そうですし
描画が軽いのはユーザの利益にも繋がると思ったので
ざっくりとクラスも公開してしまいます。
チューニング情報くらいしかない、地味なブロガーとしては非常に嬉しく思っとります。
ありがとうございます。
そしてまた飽きもせずチューニング話です。
今まではプログラム的なものが多かったので
たまには、描画速度やらを検証してみたので公開します。
そして今回は何気にニーズが多そうですし
描画が軽いのはユーザの利益にも繋がると思ったので
ざっくりとクラスも公開してしまいます。
はじめに
今回の検証結果とクラスは、主に検索系のUIや
一覧を表示する系のFlashで効果を発揮します。
Flashでのコンテンツ制作では、ライブラリに、アイテムの背景だとかアイコンだとか
要するに描画上の変化が無く ただ表示するだけ のものが結構あると思います。
何気なく生成しているこのパーツを
より早く・より軽く・効率的に扱うことが出来れば
全体のパフォーマンスに大きな変化をもたらす事が出来る。
そう考えたのが、今回の検証のきっかけです。
(内容とか結果とかいいからクラスだけさっさとくれよ
というひとは一番下まで読み飛ばしてください。)
getDefinitionByName は若干遅いよ
一般的に、リンケージをつけたシンボルは
以下の方法で動的に生成が可能です。
var clazz:Class = getDefinitionByName(リンケージ名) as Class; new clazz();とはいえ、この方法ではわざわざ
getDefinitionByName にリンケージ名を指定してから new する
という非常に面倒な方法を取らねばなりません。
これがおっくうだという人も居るんじゃないでしょうか。
しかもこれ、毎回実行すると若干遅いです。
もし何度も同じリンケージシンボルを作る場合は
一度参照解決したクラスは使いまわすようにしましょう。
// 毎回 getDefinitionByName する場合. -----------------------------
for( var i:uint = 0; i < 10000; i++ ){
var clazz:Class = getDefinitionByName(リンケージ名) as Class;
new clazz();
}
// 230ms
// getDefinitionByName を一回だけする場合. ---------------------
var clazz:Class = getDefinitionByName(リンケージ名) as Class;
for( var i:uint = 0; i < 10000; i++ ){
new clazz();
}
// 200ms
この通り若干ではありますが速度差があります。とはいえコレは生成コストは変わりますが、肝心の描画コストは変わりません。
というわけで描画コストを下げる方法を探ります。
cacheAsBitmap を使おう
これは複雑なシェイプやテキストを扱う上では鉄板中の鉄板ですね。
描画管理を一度ビットマップにキャッシュすることで、飛躍的に描画速度があがります。
リンケージシンボルが画像データでなないかぎり
cacheAsBitmapしてあげるのが、高速化への第一歩です。
(中身が既に画像のシンボルをcacheAsBitmapすると生成コストが上がり逆効果)
まだ使ったことが無い人は、だまされたと思って使ってみてください。
ひとまずありとなしのサンプルをどうぞ(注:重いです)
opaqueBackground の指定をしよう
cacheAsBitmapを行った際に特に意識してもらいたい項目です。
表示すべきシンボルで、透過すべき領域の色が確定している場合には
cacheAsBitmapと併せてopaqueBackgroundを指定すると更に速くなります。
例えば上の画像のようなシンボルや、テキストの描画では
以下の実装をすると描画コストが下がります。お試しあれ。
ちなみにサンプルはこちら。ただ、マシンによっては差が解りにくいかも。
cacheAsBitmap = true; opaqueBackground = 0xffffff;
まだまだ速くしたいぞ
上記の3つに気をつけるだけでも、結構な速度改善があるのですが
まあこの程度の検証は色々な所でされていますので、もう一歩踏み込みんでみます。
むしろここからがこの記事の最も言いたかった事です。
今から説明する方法は、現在の自分の経験上、生成コストも描画コストも最速です。
その方法とは
初回生成時にリンケージシンボルを bitmapData に draw して Bitmap クラスで使いまわす
という、よく考えると当たり前すぎる方法です。
この方法をとると、3000個のリンケージシンボルを生成する際に
生成時間が僕の環境では 140ms -> 70 ms と短くなっただけでなく
fpsも環境によっては倍近く変わるというなかなかの効きっぷりを見せてくれました。
しかも、bitmapDataを使いますのでメモリの使用量も最小に抑えられます。
サンプルはこちら。
<追記>
なんか一部マシンによって結果が変わるかも・・・Flashおそるべし・・・
というわけでクラス公開
いろいろ説明されたけどよくわからんとか
そんなん意識するの面倒だし、実装もめんどうだよ
とかそういう人の為に、今日の内容を簡単にまかなってくれる
クラスとサンプルを公開します。(使う人居るかはわからないけど・・・)
StLinkageSymbolFactory.zip
使い方は以下のような感じで簡潔です。
import して使うだけ。Staticクラスなので、特に準備もいらないです。
import jp.flair4.core.display.StLinkageSymbolFactory;
// リンケージ名 hoge のアイテムを生成する.
var hoge:DisplayObject = StLinkageSymbolFactory.create("hoge");
// リンケージ名 fuga のアイテムを画像化して取得する.
var fuga:Bitmap = StLinkageSymbolFactory.createAsBitmap("fuga");
このクラスを使って createAsBitmap によってリンケージシンボルを生成すれば2回目以降は全て bitmapData を使いまわすように勝手にやってくれます。
また、リンケージシンボルが左上揃いではない(中心よせなど)場合でも
その位置を加味してBitmapしてくれたりするので便利です。
利用上の注意
とはいえ、前述したとおり、この実装が生かされるのは
あくまでも表示後に変化しないアイコンのようなパーツを作るとき限定です。
また、bitmapDataを使いまわすので、bitmapDataをいじると
全インスタンスに影響が出てしまいます。その辺はご注意ください。
また、このクラスを使って起こった如何なる問題・損害も
保障いたしかねますので、その点だけご理解いただければと。
おわりに
いままでリンケージシンボルの作成が面倒だった方
ちょっと描画速度が気になっていた方は、試してみてください。
- Newer: 生きてます
- Older: AS3.0 TextField生成処理の速度検証