S eda1a14b50ee24bcab19b62f40858e76 PHP メモリ管理

調査方法

// 現在のメモリ使用量を知ることができる
echo memory_get_usage();

// メモリの最大量。これを超えると落ちる。
echo ini_get('memory_limit'); 

循環参照をなくすには

case 1 ○

foreach (range(1,1000) as $i){
    $obj = new StdClass;
}
毎回 new してるためメモリが増えそうだが、リファレンスカウントGCのおかげで使われなくなったオブジェクトは解放される。$obj をvar_dumpしてみると、おもしろいことに、#1, #2, #1, #2 と順繰りになっている。

#1が生成→$obj (#1のリファレンスカウントは1)
#2が生成→$obj (#2のリファレンスカウントが1になり、#1が0。よって#1を破棄)
#1が生成→$obj (#1のリファレンスカウントが1になり、#2が0。よって#2を破棄)
...


case 2 ×

foreach (range(1,1000) as $i){                        
    $obj = new StdClass;         // obj1(1)
    $obj->child = new StdClass;  // obj1(1) obj2(1)            
    $obj->child->child = $obj;   // obj1(2) obj2(1)
    unset($obj);                 // obj1(1) obj2(1)
}
循環参照の例。こうするとがんがんメモリを食っていく。

case 3 ○

foreach (range(1,1000) as $i){                        
    $obj = new StdClass;         // obj1(1)       
    $obj->child = new StdClass;  // obj1(1) obj2(1)            
    $obj->child->child = $obj;   // obj1(2) obj2(1)
    unset($obj->child);          // obj1(1) obj2(0)
}
obj2をunsetすればOK
obj2が破棄されることでobj1への参照もなくなっている?

unset($obj->child); ではなく、unset($obj->child->child); でもOK。
$obj1のリファレンスが0になるから、$obj2もなくなる?

$objというローカル変数を持っていなければならないというのがやっかいなんだな。

case 4 ×

class Hoge{
    public $moge;
    function __destruct(){
        unset($this->moge);
    }
}
foreach (range(1,1000) as $i){
    $obj = new Hoge;
    $obj->moge = new Hoge;
    $obj->moge->moge = $obj;
}
destructorとやらを使えばなんとかなるんじゃね?と思ってやってみたが、だめだった
__destructが呼ばれるのは参照カウントがなくなってかららしい…。

case 5 ○

class Hoge{
    public $moge;
    function destruct(){
        unset($this->moge);
    }
}
foreach (range(1,1000) as $i){
    $obj = new Hoge;
    $obj->moge = new Hoge;
    $obj->moge->moge = $obj;
    $obj->destruct();
}
手動でやればいいんだけどさ。case3とたいして変わらん。可読性は良くなるけど。今のところこれが最善かなぁ。

もしかして

    他の人の「PHP メモリ管理」

    S eda1a14b50ee24bcab19b62f40858e76

    無所属ソフトウェアエンジニア

    (1722words)

    最新

      最新エントリ