メモリとは
メモリとは、コンピュータにおいてプログラムやデータを記憶する装置のことである。
よく机に例えられて説明されることが多いが、そのメモリに不要なデータが解放されずに残り続けることによって、メモリオーバーのエラーになる
ことがある。
その不要なメモリを解放するためについて、簡単に以下にまとめる。
この記事の参考資料↓
メモリが解放される条件(変数)
定義した変数のデータは、解放されない限りメモリに残り続ける。
◎解放される条件は以下の通り↓
- 「実際のデータの参照が一つ無効になる」時、zvalの参照カウント(zvalのrefcount)を-1した結果、0であればデータはメモリから消滅する。
- Garbage Collection Cycleの結果、参照カウントが0であれば、データはメモリから消滅する。
※詳しくは先ほどのリンクを参照!
まあ、定義した変数が全て使い終わったら…、というイメージで捉えておく。
1) 変数の有効範囲の消滅
変数の使用できる範囲から逃れる時、その有効範囲自体の消滅と同時に、変数は解放され、実際のデータの参照も無効になる。
function sampleFunc() {
$local = 'a'; //$localは、function{}の範囲内で有効です。
}
sampleFunc(); // 関数の遂行が合わったあと、a関数内の$localは自動的に解除されます。
2) 明示的な変数シンボルの解除(unset)
phpでは、変数を明示的に開放できるunset()という関数がある。
unset($local) : void
3) 変数シンボルの参照再設定
変数シンボルの参照が再定義されると、以前の参照は無効になる。
$a = array(0);
$a = array(1); //この時、$aの変数の参照がarray(1)に上書きされ、array(0)に対する参照は無効になる。
メモリが解放されない条件
- 「実際のデータの参照が一つ無効になる」時、参照カウント(refcount)が「1以上」であれば、データは消滅せずに残り続ける。
1) 同じスコープで、同じデータを参照する変数がある場合
同じ関数内などの同じスコープで、同じデータを参照する変数が複数存在する場合、一つの変数が解放されても、データは消滅しない。
$a = array(0);
$b = $a;
unset($a);
var_dump($b); //$aの変数を解除しても、$bがarray(0)の参照を持っているため、消滅しない。
2) 違うスコープで、同じデータを参照する変数がある場合
関数の引数として渡された場合などは、上位スコープでまだデータを参照しているため、現在のスコープから変数が解除されても、データは消えない。
function sampleFunc(object $obj) {
unset($obj);
//現在のスコープの$objに対する参照は解放される。
//しかし、上位スコープにいる$aの変数の参照がまだ有効なため、データは消滅しない。
}
$a = array(0); // このarray(0)は残っている。
sampleFunc($a);
3) compound typeの変数の内部で、同じデータを参照する変数がある場合
array, objectなどのcompound typeは、内部にデータは参照を持つことができる。
その内部でデータを参照していると、データは消滅しません。
function x(object $obj) {
$data = array(0);
$obj->data = $data;
//$dataは、x関数の遂行後に解除されますが、stdClassのインスタンスのメンバーとして、array(0)データを参照することになり、データは消滅しません。
}
$a = new \stdClass;
x($a);
最後に
メモリの概念を理解することで、効率よくデータを扱えそうなので、勉強していきたい。
また、メモリリーク、ガベージコレクションについての記事もまとめる。