ガーベッジコレクションを実感してみる

Tweener業界標準的存在なのでめっきり使わなくなったfl.transitions.Tween(AS2.0ではmx.transitions.Tween)クラス。これを使って途中でトゥイーンが止まってしまう現象があったので調べていると原因はガーベッジコレクションであることがわかりました。

そこで実証サンプルを作ってみました。途中で参照が断ち切られ、トゥイーンが止まる事が実感できると思います。

サンプルは以下から。

ガーベッジコレクションのサンプル

http://clockmaker.jp/labs/080627_gc_tween/main.swf

ガーベッジコレクションの監視はGCWatcher:GCの起動とオブジェクトの回収状況を監視するための方法 - プログラミングとかそんなのから拝借しました。ありがとうございます。
どうでしょう?10秒ほど時間がたつと参照が断ち切られアニメーションが途切れてしまうのが確認できると思います。System.gc()ボタンはそのメソッドを行うボタンで、それを押した瞬間にも参照が断ち切られるのが分かると思います。

問題になっているスクリプト部分

ローカル変数(雪のDisplayObject)をTweenに指定しているのがまずいんですね。
※ちなみにTweeerに書き直したら問題はありませんでした。

var snow:Sprite = new Snow(); //Snowはリンケージ指定したMC
snow.x = stage.stageWidth * Math.random();
			
addChild(snow);
watcher.watch(snow); //watcherはGC監視インスタンス
			
var tw:Tween = new Tween(snow,"y", Regular.easeIn, 0, stage.stageHeight, time, true);
tw.addEventListener(TweenEvent.MOTION_FINISH, function(event:TweenEvent)
{
    event.target.removeEventListener(TweenEvent.MOTION_FINISH, arguments.callee);
    removeChild(snow);
});

つまりローカル変数は一定時間後にGCが起動した際に参照が断ち切られるので、Tweenを行っている間に参照が消えるとアニメーションさせようにも対象のインスタンスを取得できずモーションが止まってしまうのです。ローカル変数でなくクラス変数やタイムライン変数、もしくはどこかに参照を保存しておけば問題ないのですが、気をつけないといけないですね。AS2ではこの書き方で問題なく動いており、AS3だとつまずいたので言語を移行する人は注意が必要です。

ガーベッジコレクションは数年前に存在を知り、最近はてなで話題に上がる事が増えましたが、イマイチその事象で困ることがありませんでした。このサンプルを試して実感が一つわきました。