PHP - 函数返回赋值的性能降低

时间:2016-08-02 15:10:51

标签: php performance function variable-assignment

作为项目的一部分,我遇到了这种情况,在循环内部,我存储函数返回的值。 这恰好是应用程序的瓶颈,大型数组将需要永远处理。

对我而言,任务应该没有理由让人难以置信的缓慢表现。 另一方面,相同的函数调用,返回时没有赋值,可以提供更好的性能。

你能解释一下为什么第一个循环要慢得多吗?

Output: First took 1.750 sec. Second took 0.003 sec.

class one {

    private $var;

    public function __construct() {
         $this->var = array();
    }

    public function saveIteration($a) {     
        $this->var[] = $a;
        return $this->var;
    }

    public function getVar() {      
        return $this->var;      
    }
}

$one = new one();    
$time_start = microtime(true);

for ($i = 0; $i < 10000; $i++) {
    $res = $one->saveIteration($i);
}    
echo "First took " . number_format(microtime(true) - $time_start, 3) . " sec.";

$time_start = microtime(true);

for ($i = 0; $i < 10000; $i++) {
    $one->saveIteration($i);
}  

$res = $one->getVar();
echo "<br>Second took " . number_format(microtime(true) - $time_start, 3) . " sec.";

3 个答案:

答案 0 :(得分:1)

根据http://php.net/manual/en/functions.returning-values.php#99660,数组返回值不通过引用传递,而是按值传递。这意味着创建了一个数组的副本(至少,当你再次更改它时),这反过来需要时间来实际创建副本(分配内存,memcopy数据)。

答案 1 :(得分:0)

@Jakumi提出了一个很好的观点。由于在分配时必须复制值,因此在第一个循环中需要10,000个额外的操作和更多的内存。

两个循环之间的差异实际上远大于测试显示。如果在两个测试之间,您重置为:

,那么您的比较会更公平
unset($one); $one = new one();

在当前的测试中,第二个循环正在执行,同时仍然保留内存中第一个循环的大数组,因此结果不是独立的。见this modification

答案 2 :(得分:0)

这可能与您创建10.000阵列的事实有关;每次将 new 数组的元素数量增加1个元素。

我猜你在循环中时局部变量本身没有被释放;因此,我继续前进尝试使用未设置释放它,结果非常接近。

我知道这不是一个现实世界的例子;但是在你的代码中,如果你有类似的东西,你可以通过在完成它后释放(取消设置)局部变量来逃脱它

这是你的测试代码:

class one {

    private $var;

    public function __construct() {
         $this->var = array();
    }

    public function saveIteration($a) {
        $this->var[] = $a;
        return $this->var;
    }

    public function getVar() {
        return $this->var;
    }
}

$one = new one();
$time_start = microtime(true);

for ($i = 0; $i < 10000; $i++) {
    $res = $one->saveIteration($i);
    unset($res);
}
echo "First took " . number_format(microtime(true) - $time_start, 3) . " sec.".PHP_EOL;

$time_start = microtime(true);

for ($i = 0; $i < 10000; $i++) {
    $one->saveIteration($i);
}

$res = $one->getVar();
echo "Second took " . number_format(microtime(true) - $time_start, 3) . " sec.".PHP_EOL;

注意:我唯一修改的是在第一个例子中添加未设置

结果:

  • 首先花了0.068秒。
  • 秒花了0.062秒。