1

テスト 1:

class Entity { }

$entities = array();
echo "START: ". number_format(memory_get_usage()) . "\n";
for($i = 0; $i < 100000; ++$i)
{
    $entities[] = new Entity();
}
echo "BEFORE UNSET: ". number_format(memory_get_usage()) . "\n";
unset($entities);
echo "AFTER UNSET: ". number_format(memory_get_usage()) . "\n";

出力:

START: 631,664
BEFORE UNSET:44,404,904
AFTER UNSET: 8,954,568

テスト 2:

class Entity { }

$entities = array();
echo "START: ". number_format(memory_get_usage()) . "\n";
for($i = 0; $i < 100000; ++$i)
{
    $entity = new Entity();
    $entities[] = &$entity;
}
echo "BEFORE UNSET: ". number_format(memory_get_usage()) . "\n";
unset($entities);
echo "AFTER UNSET: ". number_format(memory_get_usage()) . "\n";

出力:

START: 631,664
BEFORE UNSET: 10,480,480
AFTER UNSET: 631,752

メモリ制限に苦労した後、少しいじってみました...

その後、ガベージコレクションが実際にどのように機能するのか疑問に思います:

  1. テスト1がテスト2より多くのメモリを必要とするのはなぜですか?
  2. テスト1で配列を設定解除した後、phpがメモリを保持するのはなぜですか?

thxデイブ

4

2 に答える 2

1

テスト1がテスト2よりも多くのメモリを必要とするのはなぜですか?

PHPは、参照よりも多くのメモリを識別子の格納に割り当てます(最初のテストでは識別子によって割り当てられます)。

マニュアルから:

PHP参照はエイリアスであり、2つの異なる変数が同じ値に書き込むことができます。PHP 5以降、オブジェクト変数にはオブジェクト自体が値として含まれなくなりました。これには、オブジェクトアクセサが実際のオブジェクトを見つけることができるオブジェクト識別子のみが含まれています。オブジェクトが引数によって送信されたり、返されたり、別の変数に割り当てられたりする場合、異なる変数はエイリアスではありません。同じオブジェクトを指す識別子のコピーを保持します。

これにより、識別子はやや魔法のようになり、特別に処理されます。

テスト1で配列の設定を解除した後、PHPがメモリを保持するのはなぜですか?

unsetGCのアルゴリズムによって解放するために変数のメモリをマークするだけです。そのときはメモリを解放しません。最初のテストを実行すると、かなりの量のメモリが解放されます(ただし、割り当てられているサイズが大きいため、2番目のテストほどではありません)。

于 2012-04-05T18:45:07.663 に答える
1
  1. 最初のものは、実際のオブジェクトを配列の各値に保存しているため、配列の設定を解除しても、それらのオブジェクトはまだそこに残っています。
    • これが、この配列がより多くのメモリを消費する理由です-実際のオブジェクトを格納しています
  2. 2 つ目は、オブジェクトへの参照 (for ループのスコープ内にのみある) を保存するだけで、それらが設定解除されると、オブジェクトはなくなります。
    • この配列が消費するメモリが少ない理由は、オブジェクトへの参照のみを格納しているためです。

したがって、ここにあることを行う場合:

$entities = array();
echo "START: ". number_format(memory_get_usage()) . "\n";
for($i = 0; $i < 100000; ++$i)
{
    $entities[] = new Entity;
}
echo "BEFORE UNSET: ". number_format(memory_get_usage()) . "\n";
foreach($entities as &$entity) {
    unset($entity);
}
unset($entities);
echo "AFTER UNSET: ". number_format(memory_get_usage()) . "\n";

そして、配列内の各オブジェクトの設定を解除します。2 回目の試行と同じ結果が得られます。

例:

開始: 3,237,720 設定解除
前: 21,297,640 設定解除後
: 3,237,488

デモ: http://codepad.org/oUjzA46D

于 2012-04-05T17:59:39.007 に答える