PHP性能:复制与参考

fre*_*oma 8 php benchmarking reference php-internals

嘿.今天我编写了一个小的基准脚本来比较复制变量的性能与创建对它们的引用.我期待,例如,创建对大型数组的引用将比复制整个数组慢得多.这是我的基准代码:

<?php
    $array = array();

    for($i=0; $i<100000; $i++) {
        $array[] = mt_rand();
    }

    function recursiveCopy($array, $count) {
        if($count === 1000)
            return;

        $foo = $array;
        recursiveCopy($array, $count+1);
    }

    function recursiveReference($array, $count) {
        if($count === 1000)
            return;

        $foo = &$array;
        recursiveReference($array, $count+1);
    }

    $time = microtime(1);
    recursiveCopy($array, 0);
    $copyTime = (microtime(1) - $time);
    echo "Took " . $copyTime . "s \n";


    $time = microtime(1);
    recursiveReference($array, 0);
    $referenceTime = (microtime(1) - $time);
    echo "Took " . $referenceTime . "s \n";

    echo "Reference / Copy: " . ($referenceTime / $copyTime);
Run Code Online (Sandbox Code Playgroud)

我得到的实际结果是,recursiveReference只需20次(!)就像recursiveCopy一样长.

有人可以解释这个PHP行为吗?

mea*_*gar 17

PHP很可能会为其数组实现copy-on-write,这意味着当您"复制"一个数组时,PHP不会完成物理复制内存的所有工作,直到您修改其中一个副本并且您的变量不再引用相同的内部代表.

因此,您的基准测试存在根本缺陷,因为您的recursiveCopy函数实际上并未复制对象; 如果确实如此,你会很快耗尽内存.

试试这个:通过分配数组元素,你可以强制PHP 实际复制.你很快就会发现内存耗尽,因为在递归函数达到最大深度之前,没有任何副本超出范围(并且不会被垃圾回收).

function recursiveCopy($array, $count) {
    if($count === 1000)
        return;

    $foo = $array;
    $foo[9492] = 3; // Force PHP to copy the array
    recursiveCopy($array, $count+1);
}
Run Code Online (Sandbox Code Playgroud)