現在の言語: 日本語

戻る

ガベージコレクション
メモリ解放関連

ガベージコレクションについて
PHPスクリプト内で不要になったメモリを自動的に解放するメカニズムです。主に参照カウントと、循環参照を検出・処理するためのサイクル検出アルゴリズムを組み合わせて機能します。
参照カウント
変数やオブジェクトが作成されると、そのメモリ領域の「参照カウント」が増えます。
別の変数が同じものを参照すると、カウントが増加します。
参照がなくなると参照カウントが減少します。
カウントがゼロになると、即座にメモリが解放されます。
しかし、参照カウント方式によるメモリ解放処理の方法では
循環参照を解消できません。
※循環参照とはオブジェクトAがオブジェクトBを参照しているのに、オブジェクトBもオブジェクトを参照しているため
お互いを参照しあっている状態です。
このため参照カウントが0になることがありません。
このため、サイクル検出をしてガベージコレクションで解放処理を試みます。

サイクル検出
PHPでは、ルートバッファと呼ばれる領域に一定数の「孤立した」参照が溜まった時などの条件に一致した場合、
ガベージコレクタが起動し、これらの循環参照を検出してメモリを解放します。


[サンプル]

copy
//循環参照の例
class test1
{
	public object $data1;
}
class test2
{
	public object $data2;
}
echo "<pre>";

//GCの自動実行を一時的に無効にします。
//循環参照が発生する環境を作ります。
gc_disable();

//循環参照をつくる準備をします
$cls1 = new test1();
$cls2 = new test2();
//お互いを参照させる(循環参照にsます)
//外部からの参照を解除します
//ここで $cls1と$cls2は外部からアクセスできなくなります。
//お互いに参照し合っているため、参照カウントはゼロになりません。
//この時点ではメモリは解放されず、リークした状態になります。
$cls1->data1 = $cls2;
$cls2->data2 = $cls1;

//unsetを実行して外部参照を切断します
//しかし、unsetを実行しても循環参照によりメモリは解放されません
unset($cls1);
unset($cls2);

//強制的にガベージコレクション(サイクル検出)を実行します
$count = gc_collect_cycles();

//2個の循環参照が収集され、メモリが解放されました。
echo $count . "個の循環参照が収集され、メモリが解放されました。\n";

//後片付けします
gc_enable();

echo "</pre>";
copy
//Example of a circular reference
class test1
{
	public object $data1;
}
class test2
{
	public object $data2;
}
echo "<pre>";

//Temporarily disable automatic GC execution.
//Create an environment where a circular reference can occur.
gc_disable();

//Prepare to create a circular reference
$cls1 = new test1();
$cls2 = new test2();
//Make them reference each other (creating a circular reference)
//Remove external references
//Now, $cls1 and $cls2 can no longer be accessed externally.
//Because they still reference each other, the reference count will not reach zero.
//At this point, memory will not be released and will be leaked.
$cls1->data1 = $cls2;
$cls2->data2 = $cls1;

//Execute unset to break external references.
//However, executing unset does not free memory due to circular references.
unset($cls1);
unset($cls2);

//Force garbage collection (cycle detection).
$count = gc_collect_cycles();

//Two circular references were collected and memory was freed.
echo $count . "Circular references were collected and memory was freed.\n";

//Clean up.
gc_enable();

echo "</pre>";



gc_enable()ガベージコレクタ(サイクル検出メカニズム)の自動実行を有効にします。PHPの実行環境ではデフォルトで有効になっています。
gc_disable()ガベージコレクタ(サイクル検出メカニズム)の自動実行を無効にします。参照カウント自体は機能し続けますが、循環参照によるメモリリークが蓄積し始めます。
gc_collect_cycles()gc_disable()で無効な状態であっても、あるいは有効な状態であっても、その時点で強制的にサイクル検出とメモリ解放プロセスを実行します。
gc_disable()によって、PHPが自動的にサイクル検出コレクタを起動するのを防ぎます。
$cls1->data1 = $cls2;
$cls2->data2 = $cls1;
お互いを参照することで循環参照を生じさせています。
unset($cls1);
unset($cls2);
参照を切断します。

gc_collect_cycles() を呼び出した瞬間に、
PHPのガベージコレクタがメモリ内をスキャンします。
到達不可能な循環参照のグループを検出し、それらを一括で解放します。
このようにガベージコレクションによるサイクル検出をすることで
循環参照などにより引き起こされるメモリリークを解決する機能します。



戻る

著作権情報
ホームページおよプリ等に掲載されている情報等については、いかなる保障もいたしません。
ホームページおよびアプリ等を通じて入手したいかなる情報も複製、販売、出版または使用させたり、
または公開したりすることはできません。
当方は、ホームページおよびアプリ等を利用したいかなる理由によっての障害等が発生しても、
その結果ホームページおよびアプリ等を利用された本人または他の第三者が被った損害について
一切の責任を負わないものとします。