作为项目的一部分,我遇到了这样的情况:在循环中,我存储函数返回的值。这恰好是应用程序的一个瓶颈,因为处理大型阵列需要很长时间。
对我来说,这项任务不应该成为令人难以置信的缓慢表现的理由。另一方面,相同的函数调用,返回时没有赋值,可以提供更好的性能。
你能解释一下为什么第一个循环慢得多吗?
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.";
根据http://php.net/manual/en/functions.returning-values.php#99660数组返回值不是通过引用传递的,而是通过值传递的。这意味着创建了数组的副本(至少,当您再次更改它时),这反过来又需要时间来实际创建副本(分配内存、memcopy数据)。
这可能与创建10.000个数组有关;每次将新数组的元素数量增加1个元素。
我猜,当你在循环中时,局部变量本身并没有被释放;因此,我继续前进&尝试使用unset释放它,结果非常接近。
我知道这不是一个真实的例子;但是在你的代码中,如果你有类似的东西,你可以在完成后释放(取消设置)本地变量
这是你的测试代码:
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;
注意:我唯一修改的是在第一个示例中添加unset
结果:
- 第一次花了0.068秒
- 秒耗时0.062秒
@Jakumi提出了一个很好的观点。由于赋值时必须复制值,因此在第一个循环中需要10000个额外的操作和更多的内存。
两个循环之间的差异实际上比测试显示的要大得多。如果在两次测试之间,你用重置,你的比较会更公平
unset($one); $one = new one();
在当前的测试中,第二个循环正在执行,同时仍将第一个循环中的大数组保存在内存中,因此结果不是独立的。请参阅此修改