Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/252.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带有对象的PHP内存不稳定数组_Php - Fatal编程技术网

带有对象的PHP内存不稳定数组

带有对象的PHP内存不稳定数组,php,Php,测试一: 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($entiti

测试一:

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";
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";

测试二:

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";
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";
在我遇到内存限制的问题后,我对它进行了一些尝试

在那之后,我想知道垃圾收集到底是如何工作的:

  • 为什么测试一比测试二需要更多的记忆
  • 在testone中取消设置数组后,为什么php会保留内存
  • 戴夫夫人

  • 第一个是将实际对象保存到数组中的每个值,因此,当您取消设置数组时,这些对象仍然存在。
    • 这就是这个数组占用更多内存的原因——它存储的是实际对象
  • 第二种方法是保存对对象的引用(仅在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";
    
    $entities=array();
    回声“开始:”。数字\格式(内存\获取\使用()。“\n”;
    对于($i=0;$i<100000;++$i)
    {
    $entities[]=新实体;
    }
    回声“在未设置之前:”。数字\格式(内存\获取\使用()。“\n”;
    foreach($entities as&$entity){
    未结算(实体);
    }
    未结算(实体);
    回声“未设置后:”。数字\格式(内存\获取\使用()。“\n”;
    
    然后取消设置数组中的每个对象。您将获得与第二次尝试相同的结果:

    例如:

    开始:3237720
    未设置前:21297640
    取消设置后:3237488

    演示:

    为什么测试一比测试二需要更多的内存

    PHP为存储标识符分配的内存比为引用分配的内存多(您的第一个测试是按标识符分配的)

    从:

    PHP引用是一个别名,它允许使用两个不同的变量 写入相同的值。从PHP5开始,对象变量不起作用 不再将对象本身作为值包含。它只包含一个对象 允许对象访问器查找实际对象的标识符。 通过参数发送、返回或分配给另一个对象时 变量,不同的变量不是别名:它们包含 指向同一对象的标识符

    这使得标识符有点神奇,它们是经过特殊处理的

    为什么php在测试一中取消设置数组后仍保留内存


    unset
    仅标记一个变量的内存以供GC的算法释放;它无法立即释放内存。当我运行您的第一个测试时,大量内存被释放(虽然没有第二个测试那么多,可能是因为分配了更大的大小)。

    您所说的
    这些对象仍然在那里是什么意思?@webbiedave它们仍然在内存中的某个地方。还没有超出范围。这基本上不是我的答案所说的吗?不。你的答案
    它存储的是实际对象
    是不正确的。您的回答也没有提到标识符,这些标识符绝不是实际对象(请尝试
    $entity=newentity();$entities[]=$entity;
    )。我的回答也回答了他的第二个问题,即为什么与你的完全不同。标识符的优势是什么?为什么php使用标识符而不是引用?