10 Tips for Flex Application Performance | InsideRIA
We’re going to keep this post lean and mean, and get down to business with 10 Tips that will keep your Flex applications fast, lean, and responsive.
よくまとまっているなーと思いながら読んでいて、これは訳したらキャッチーなんじゃないかという不純な動機で、途中失速しつつもなんとか勢いに任せてやってみました。
ルール #1: 後片付けはしっかりと
いつでもきれいなコードを書くのは大事なことだ。整理されて読みやすいだけでなく、その挙動(CPUを食いつぶしたり、メモリリークをおこしたり、CGの対象にならないオブジェクトを残したり)もね。
1 ) イベントリスナーを管理する
不要になったリスナーはかならず削除すること。これには2つの理由がある。
ひとつめは、オブジェクトを参照し続けて、GCが回収するのを邪魔してしまうこと。これは見つけにくいパフォーマンス低下要因になってしまう。
メモリを節約するために弱参照にすることもできるけど、やっぱり不要になったものは明示的に削除したほうがいいね。
ふたつめは、リスナーが残っていること自体がパフォーマンスに悪い影響をおよぼすということ。
君が気づいていなくても、登録されたリスナーはイベントごとに呼ばれ続けている。
DOMツリーで親子になっているコンポーネントがあって、子のみにイベントを起こしたつもりでも、親に登録されているリスナーにも同じイベントが起きてしまう。
それを防ぐためには、リスナーが適切なタイプのイベントのみハンドルするように指定して、リスナーが不要になったらすぐに削除する必要があるんだ。
2 ) ローダーはアンロードする
ローダー(Image, SWFLoaderなど)でオブジェクトを使ったときには、”unloadAndStop()”を呼んでそれらをアンロードし、GCを起動したほうがいい。
これで貴重なリソースを解放して、不要なことにCPUを使わなくてすむ。僕はたいてい静的イメージファイルにも同じことをしているよ。メモリを節約するためにね。
3 ) いらないものは捨てる
僕は、データマネージャやビューアなどのカスタムコンポーネントを作ったときに”dispose()”を持たせるといいことに気がついた。この中で使ったリソースを解放するんだ。
このメソッドはオブジェクトを使い終わったときや、明示的にリソースを解放したいときに呼ぶ。
たとえばタイマーを止めたり、イベントリスナーを削除したり、またはオブジェクトをローダーからアンロードしたり、変数にnullを設定したりなど、基本的にメモリリークを起こしたりCPUを食うようなことを取り除く。
もちろん”dispose()”を呼ぶこともCPUを食うよ。でも僕を信じてくれ、それらをしないことで無駄にする時間やリソース、パフォーマンス低下に比べたら、デメリットはずっと小さいから。
ルール #2: やる必要がないことはやらない
つぎのルールは「やる必要がないことは、やらない」だ。いやいや、仕事をしなくてもいい、だとか、歯を磨かなくてもいい、なんてことは言ってないよ。それらは生きていくために必要じゃないか。
僕が言いたいのは、不要なことに気を使ったり無駄なことに力を浪費したりしないように、ということだよ。
4 ) コレクションは正しく使う
僕がコレクション(ArrayCollection, XMLListCollectionなど)に出会ったときに、いつも最初にやることがある。
それは、arrayやxmllistなどのプリミティブ型をラップするヘルパークラスを作ることだ。
コレクションクラスではプリミティブ型を簡単に使うために、君が気づかないところで負荷がかかってしまっている。
アイテムを追加、更新したり、削除するたびにイベントが起きているんだよ。コレクションをリフレッシュ(ソートやフィルタリング)するときにもね。
最初の秘訣はコレクションのイベントを意識すること。
もし100,000個のアイテムを持つコレクションをループして更新したら、100,000回のイベントが起きるんだ。
こいつが大きなパフォーマンス低下を招いたり、UIをフリーズさせたりする。もしこのイベントでなにもする必要がなければ、”disableAutoUpdate()”を使って発生を抑えることができるよ。
そうそう、作業が終わったり、またイベントを起こしたくなったら”enableAutoUpdate()”で戻せるからね。
ふたつめの秘訣は、コレクションを使う必要がないときには使わない、ということ。
100,000個のアイテムをループさせるだけなら、プリミティブ型のarrayを使えばいいんだ。コレクションを使う必要はない。
みっつめの秘訣は、コレクションをフィルタリングしたいときのみフィルター関数を使うということ。
フィルター関数を使うとコレクションにアイテムを追加するたびに”refresh()”を呼ぶ必要がなくなる。でもこれはパフォーマンス低下の要因にもなるんだ。だから、必要なときのみフィルター関数を使うこと。
たとえば、コレクションにバインドされているデータグリッドがあったとして、別の処理がそのコレクションを更新したとき、もしフィルター関数が使われていると、それらが自動的にフィルタリングされる。
すると、データグリッド全体が変更されたことになって、値の再検証と再描写が行われてしまう。
これは簡単にできることだけど、パフォーマンスに大きな影響を及ぼすことになるんだ。
5 ) 遅延インスタンス化を使う
標準では、Flexのすべてのナビゲーションコンテナ(tab nav, accordion, view stackなど)は、必要になったときにそれらの子を作る。これは、すぐに必要にならないないたくさんのコンポーネントを含んでいる場合に、それらによってアプリケーションのパフォーマンスが低下することを防いでいるんだ。
この挙動を変えるときには気をつけないと、致命的な問題になってしまうよ。
自分でカスタムコンポーネントを作るときにも、遅延インスタンス化は覚えておくべき。コンストラクターですべての子オブジェクトを作るようなことはしないように。
代わりに”createChildren()”をオーバーライドして、そこでやるべきだ。これは君のオブジェクトが遅延インスタンス化のルールに従うことになって、見つけにくいパフォーマンス低下要因になることを防ぐ。
6 ) オブジェクトを使い回すか、新しく作るか
僕はこれについて記事を書いたことがある。しかしここでもう一度言っておこう。
得てしてオブジェクトを使い回すことは、新しく作ることよりもコストが安くつく。これについてはデータ仮想化で詳しく説明しているよ。
7 ) オブジェクトに変化がないときには、無効化したり削除したり、再有効化したりしない
もしカスタムコンポーネントにバインディングしていて、その属性に(getterやsetterを通して)変更があったときに、値に変化がなければコンポーネントを無効化するべきではない。
無効化することによって、そのコンポーネントは再描写対象になってしまうんだ。
コンポーネントが再描写されるのは、オブジェクトの値が変化があったときのみにするべき。サンプルコードを載せておく。
public function set myProperty( value : Number ) : void
{
if ( _myProperty != value )
{
_myProperty = value;
propertiesChanged = true;
invalidateProperties();
dispatchEvent( new Event( "change" ) );
}
}
ルール #3: 言語は適切に使う
ActionScriptはパフォーマンス向上のための機能を備えているから、それらを積極的につかうといい。
8 ) 動的型付けと静的型付け
動的なオブジェクトは状況によって属性を変えることができて、いろいろなシチュエーションで使うことができる。
これは便利で、しかも楽だよね。しかしそれらの特徴が必要でない場合には、静的型付けされたオブジェクトをつかうべきなんだ。
静的型付けはActionScript3で導入されたもので、それを使うべき理由の一つは「速い」こと。
動的オブジェクトに比べて静的型付けされたオブジェクトは、属性へのアクセスが見逃せないほど速い。
9 ) 定数(constants)は積極的に使う
もし変更することがない、しかしあちこちで使うような値を扱うときには、定数を使うべき。
オーバーヘッドがないぶん、定数は速いよ。
10 ) 静的(static)メンバを使う
静的プロパティやメソッドは、アクセスするためにインスタンス化する必要がない。
だからクラスからすぐにアクセスできるし、アクセスのためにインスタンス化する必要がないぶんメモリを節約できるんだ。
ユーティリティメソッドや、インスタンスごとの属性を使う必要がないメソッドは、静的にすべきだ。
9番で書いている定数は、基本的に静的な定数を指している。それらはクラスのインスタンスにつくものではないから、メモリの節約のためにね。
ここで述べたことたちは小さなことだと感じるかもしれない。しかし実際に効果があることだ。
これらに気をつけることでパフォーマンスのために適切なコードが書けるはずだから、これからアプリケーションを作るときには、これらのことを気にとめておいてほしい。
コメント
[…] Flexアプリのパフォーマンスのための10のこと http://saikyoline.jp/weblog/2009/09/03/042737.html […]