プログラミングとは、すなわちメモリリークとの闘いのことであると言えます。
メモリリークのないコンテンツを作るためにはメモリ管理の仕組みを理解することが重要です。今回は、代表的なメモリ管理システム「ガベージコレクション」がどんな働きをしているのかを視覚的に見てみましょう。
なお、本記事はActionScript 3.0用のものですが、ガベージコレクションを採用している他プログラミング言語にも参考になる話です。
#そもそもガベージコレクションって?
ガベージコレクションは、不要になったメモリ領域を自動的に解放する機能です。たとえばAS3であるインスタンスを作ったとしましょう。
var mySprite:Sprite = new Sprite();
この時、メモリ上にインスタンス用の領域が確保され、メインのクラスから参照された状態となります。
次に、この参照を解除してみます。
mySprite = null;
インスタンスはどこからも参照されなくなりました。この状態の時、しばらくするとインスタンス用のメモリは自動的に開放されます。この破棄を行うのが「ガベージコレクション」という仕組みです。AS3以外にもJavaScriptやJava等、多くの言語で採用されているメモリ管理システムです。
#ガベージコレクションの働きぶりを見てみよう
ガベージコレクションは自動的に実行されるますが、AIRアプリやデバッグ用に強制的に実行させることができます。
// ガベージコレクションを強制的に実行
System.gc();
この処理が実際に実行されると、本当にメモリが開放されるのでしょうか? それを確認するために下記のようなAS3のコードを作成しました。
- Spriteクラスのインスタンスを作成
- mySpriteで参照
- 直後に参照を解除
- 10秒後にガベージコレクションを強制的に実行(メモリが開放されていることを期待)
package
{
import flash.display.Sprite;
import flash.events.TimerEvent;
import flash.system.System;
import flash.utils.Timer;
public class Main extends Sprite
{
public function Main()
{
// 1. Spriteのインスタンスを作成 2. MainクラスからmySpriteで参照
var mySprite:Sprite = new Sprite();
trace(mySprite);
// 3.Mainクラスからの参照を削除
mySprite = null;
trace(mySprite);
// 4. 10秒後にガベージコレクションを強制的に実行
var timer:Timer = new Timer(10000, 1);
timer.start();
timer.addEventListener(TimerEvent.TIMER_COMPLETE, function(event:TimerEvent):void {
// ☆ガベージコレクションを強制的に実行
trace("ガベージコレクションを強制的に実行");
System.gc();
});
}
}
}
4の部分でメモリが開放されているかを確認するには、Adobe Scoutを使います。
①の部分に注目してください。ガベージコレクションが強制的に実行されたタイミング(ソースコードで言う☆部分)のフレームにおける、処理の所要時間とメモリの変化を示しています。期待通りメモリが減っている(= mySpriteのメモリが解放されている)ことが見て取れます。また、②の部分で処理内容の正体がガベージコレクションだとわかります。
最後に
ガベージコレクションはイメージしにくいものなので、理解が難しく感じるかもしれません。しかし今回紹介したようにプロファイリングツールを使えば視覚的に、そして直感的にガベージコレクションの動きを理解できます。