- 2008-08-07 (木) 4:46
- action script
Colin Moock さんのブログにて「Things You Must Do Before Unloading a SWF File」というタイトルで紹介されています。なんのこっちゃという人、そしていまいち理解できていない僕自身のために:
事前知識その1 for Flash コンテンツ閲覧者
他のアプリケーションと同様、Flash コンテンツをブラウザで見る行為も PC のメモリを消費しています。例えば InternetExplorer ブラウザ上で Flash(swf) ファイルを見ている時、Windows ならタスクバーの上で右クリックしてタスクマネージャの「プロセス」タブで、IE が今どれぐらいメモリを消費しているかをリアルタイムで確認することができます。PC に搭載されてるメモリにも限度があるので、このメモリ消費量が増え続けるとマシン全体がメモリ不足で動きがモッサリしちゃいます。
Flash コンテンツは派手な動きをする分、メモリ消費も結構多いのですが、それを防ぐために FlashPlayer 内部処理として「もう使わないようなパーツはキレイサッパリメモリ上から消す」ということを勝手にやってくれています。これはガベージコレクション(ゴミっぽいのを収集する作業)によるメモリ解放と呼ばれています。ガベージコレクションされた瞬間にさっきの「プロセス」タブのメモリ消費量が回復するのが見れると思います。

事前知識その2 for Flash コンテンツ制作者
Flash Player が自動でガベージコレクションしてくれるんだったら、製作者は何も気にしなくていいじゃん。で済めばいいのですが、Flash の作り方によってはガベージコレクションしてくれる「ガベージコレクター」さんが「これはゴミなのか?それともあとで使うパーツなのか?うーん消していいのかどうかワカンネ。」となってしまう場合があります。制作者的にはもう不要なのでガベージコレクションしてメモリ解放してくれよと思っているのにしてくれない時があるのです。そんなときは製作者側で「このタイミングでこのパーツ(オブジェクト)は金輪際使わないのでキレイサッパリ削除!」という感じで「強制ガベージコレクション」してやる必要があるのです。(この作業が面倒、というかいまいち理解できてないんです。僕)
事前知識その3 for Flashコンテンツ制作者 -実践編-
じゃあ「強制ガベージコレクション」しようってなったら、この辺の記事を読んで勉強すればいいのね。ガベージコレクションされたかどうかの確認なんだけど、さっきのタスクマネージャーでの確認はいまいちあてにならない(というのも FlashPlayer がガベージコレクション(以下GC)してくれるのと同様に IE や FireFox ブラウザ側でも GC してくれるので正確に FlashPlayer による GC なのかが確認しづらい)のです。ちゃんと Flash(ActionScript) でメモリ消費を確認する仕組みも用意されているので、
「ASのガベージコレクトは参照カウント方式じゃなかった (www.imajuk.swf)」
様の下のコードみたく、デバッグ用として Flash のテキストフィールドにメモリ消費量を表示させるのが一番正確。
追記:コメントをいただきました。GC自体が負荷の高い処理だということ(それでAS3でGCの仕様が変わったらしいことを以前読んだことがあります。)と、Flex のプロファイラが一番正確(僕はあいにく Flash × FlashDevelop ですけど)とのことですー。
という認識で合ってますでしょうか?
で、GC の対象になるのは、使わなくなったオブジェクト・画像・外部ロードした SWF ファイルなどなどいっぱいあるのだけど、今回は外部ロードした SWF ファイルを GC するための方法について。
以下なんとなく翻訳:
原文:Things You Must Do Before Unloading a SWF File
Flash Player 9 & ActionScript3 環境にて .swf をロードし、その後削除してメモリ上からもキレイサッパリ消したい場合は、まず動きを止めて(deactivate)、それから参照を切る(dereference)必要があります。動きを止める前に参照を切ろうとしても、そのままリソースを食い続け、ガベージコレクションの対象にならない場合があるのです。
非公式ですが .swf ファイルを deactivate するためのチェックリストを掲載しておきます。
- Tell any loaded .swf child assets to disable themselves.(具体的にどういうことするの?)
- 再生しているサウンドは止める。(ロードしたswf内のだよね?)
- メインタイムラインが再生中なら Stop する。(ロードしたswf内のだよね?)
- 再生中のムービークリップも全部 Stop する。(ロードしたswf内のだよね?)
- ネットワークオブジェクト、つまり Loader, URLLoader, Socket, XMLSocket, LocalConnection, NetConnections, NetStream 等のインスタンスは接続解除しておく。(ロード途中のものは止めるとかコネクション系は close() して閉じておくってことですよね?)
- カメラやマイクの参照を切る。
- .swf 内の全てのイベントリスナーを解除(removeListenerだよね)する。特に Event.ENTER_FRAME とかマウスやキーボードに対するリスナーとか全部。
- setInterval してたら clearInterval() する。
- Timer オブジェクトを止める。Timer クラスのインスタンスメソッドである stop() を使おう。←Timerインスタンスを消す必要まではないのね。by tera
Adobe が公式に発表しているわけでもないので、このリストはまだまだ不十分かもしれないよ。もし上記リストに追加すべきことを知っていたら、僕(コリンさん)にメールしてね。(メアドは原文から確認してください。)
Flash Player 10 になれば、Loader クラスに unloadAndStop というメソッドが新規追加されて、上のようなタスクは全自動でやってくれるから便利になるよー。
もっと詳しいことを知りたい人は、コリンさんの記事「The Charges Against ActionScript 3.0」とか Grant Skinner さんの「Additional Information on Loader.unloadAndStop()」とかをご覧ください。
と訳してみたものの
結局最後に唱えるのは unload() ですよね?上記リストは deactive 作業ってことだけど、僕今まで removeListener 作業とかも「参照切り(dereference)」作業だと思ってました。なのでここでいう「dereference」作業ってのが何なのかがよくわからない。まぁ実際案件で遭遇したらブクマを参考にデバッグしながらやるからその時はその時考えることにしよ。
「AS3のLoaderで読み込んだ外部swfを確実にunloadする方法 – KAZUMiX memo」
様を参考にさせていただくといいと思います。
スタンス的には
- 基本は FlashPlayerの自動GCに任せる。
- なんか処理不可高そうな実装をしたら危機感を持つようにする。
- 低速マシンで確認してヤバそうならメモリ消費を見てみる。
- うまくGCされていない事実を知ったら:
- 負荷掛けまくりの表現を抑えるか
- 再見積りして強制GCに着手するかの2拓。
- 完成
これでいいでしょうか?まったくもって範疇外なのでよくわかってません。
追記:同じく Moock さんの著書「Essential ActionScript3.0」のP274あたりに Deactivate についての解説記事がありました。まずはこれ読むこと。
- Newer: UMap(AS 3.0) バージョン1.1の覚え書き
- Older: IE7 で見れるようになった件
Comments:5
- masa 08-08-12 (火) 3:27
-
リークしてるかしてないかのチェックはFlexのプロファイラでインスタンスが想定する数とあっているかチェックするのが一番確実です。
異常に増え続けていたとしたら、それがリークしているものです。また、GCはFlashPlayerが抱えるメモリが一定(PCのスペックによりまちまちです)に達した時のみ実行されるためメモリ監視はあまり信憑性がありません。(GC自体が負荷の高い処理のためあまり頻繁に実行されません。
大抵の場合、removeEventListenerとremoveChild忘れと、クロージャが問題になります。そこを気をつけた上でこまめにプロファイラをチェックしていれば大丈夫だと思います。
- tera 08-08-12 (火) 11:05
-
>masa様
コメントいただきありがとうございます。
なるほどFlexのプロファイラがいいとのこと、そういえば去年のMAXでも聞いたことがありました。(あいにくFlex持ってないのですが。。)
PCのFlashコンテンツでは「ファンが回ったらヤバい」ぐらいの心がけでやっているのですがw、以前Wii用Flashコンテンツを作った時に、すぐにメモリ不足になってしまって困った記憶があります。どうも御丁寧にありがとうございました。
- t.g. 08-08-14 (木) 17:27
-
gabageではなく
garbageですね。 - tera 08-08-15 (金) 9:33
-
>t.g.様
ご指摘ありがとうございます。
いままでずっと間違えてました。。 - l00oo.oo00l 09-03-08 (日) 21:06
-
こんなのを作ってみました。
http://l00oo.oo00l.com/blog/archives/33
アンロードでイベントを削除するのに便利じゃないかなーと思ってます。
Trackbacks:1
- Trackback URL for this entry
- http://www.trick7.com/blog/2008/08/07-044657.php/trackback
- Listed below are links to weblogs that reference
- SWF ファイルをアンロードする前にすべきこと(と、Garbage Collection ことはじめ) from trick7
- pingback from AS3でのメモリの解放に関する記事あれこれ | SELFLASH Design 09-08-16 (日) 7:39
-
[...] Flashのメモリを制する5つの秘訣 ActionScript3.0 | メモリの解放 SWF ファイルをアンロードする前にすべきこと(と、Garbage Collection ことは