为什么foreach这么慢?

时间:2010-03-09 22:55:17

标签: php performance foreach

PHPBench.com在每个页面加载上运行快速基准脚本。在foreach测试中,当我加载它时,foreach的运行时间比第三个例子长4到10倍。

为什么本地语言结构显然比自己执行逻辑要慢?

3 个答案:

答案 0 :(得分:9)

也许它与foreach在数组副本上工作的事实有关?

或者它可能与以下事实有关:在使用foreach循环时,在每次迭代时,内部数组指针都会更改,指向下一个元素?

引用foreach's manual page的相关部分:

  

注意:除非引用了数组,   foreach在一份副本上运作   指定的数组而不是数组   本身。 foreach有一些副作用   在数组指针上。


据我所知,你链接到的第三个测试没有做这两件事 - 这意味着两个测试都没有做同样的事情 - 这意味着你没有比较两种编写相同代码的方式

(我也会说这种微优化在实际应用中根本不重要 - 但我猜你已经知道了,只是出于好奇而被问到了)

在这个测试中还有一件事感觉不对:它只进行一次测试;对于“更好”的测试,不止一次测试所有这些测试可能是有用的 - 时间大约为100微秒,不需要太多就可以产生巨大的差异。
(考虑到第一次测试在几次刷新后变化在300%和500%之间......)


对于那些不想点击的人来说,这是第一次测试(我已经获得了3xx%,443%和529%)

foreach($aHash as $key=>$val) {
    $aHash[$key] .= "a";
}

第三个(100%)

$key = array_keys($aHash);
$size = sizeOf($key);
for ($i=0; $i<$size; $i++) {
    $aHash[$key[$i]] .= "a";
}

答案 1 :(得分:2)

对不起,网站弄错了。这是我自己的脚本,显示两者的速度几乎相同,事实上,foreach更快!

<?php

function start(){
    global $aHash;
    // Initial Configuration
    $i   = 0;
    $tmp = '';
    while($i < 10000) {
      $tmp .= 'a';
      ++$i;
    }
    $aHash = array_fill(100000000000000000000000, 100, $tmp);
    unset($i, $tmp);
    reset($aHash);
}

/* The Test */
$t = microtime(true);
for($x = 0;$x<500;$x++){
    start();
    $key = array_keys($aHash);
    $size = sizeOf($key);
    for ($i=0; $i<$size; $i++) $aHash[$key[$i]] .= "a";
}
print (microtime(true) - $t);

print ('<br/>');

$t = microtime(true);
for($x = 0;$x<500;$x++){
    start();
    foreach($aHash as $key=>$val) $aHash[$key] .= "a";
}
print (microtime(true) - $t);
?>

如果查看测试的源代码:http://www.phpbench.com/source/test2/1/http://www.phpbench.com/source/test2/3/,您可以看到$ aHash在每次迭代后都没有重新填充到初始数据。它在开头创建一次,然后每次测试运行X次。从这个意义上说,你在每次迭代中使用不断增长的$ aHash ......在psuedocode中:

iteration 1: $aHash[10000000000000]=='aaaaaa....10000 times...a';
iteration 2: $aHash[10000000000000]=='aaaaaa....10001 times...a';
iteration 2: $aHash[10000000000000]=='aaaaaa....10002 times...a';

随着时间的推移,所有测试的数据对于每次迭代都会变得越来越大,因此当然通过迭代100,array_keys方法更快,因为它总是具有相同的,其中foreach循环必须与不断增长的数据集竞争并将存储在数组中!

如果你在服务器上运行我上面提供的代码,你会清楚地看到foreach更快,更整洁,更清晰。

如果网站的作者打算让他的测试做它做的事情,那么当然不清楚,否则,这是一个无效的测试。

答案 2 :(得分:0)

这种微观测量的基准测试结果应该被忽视,这些测量来自一个受到极端负载和其他影响的实时,繁忙的网络服务器。这不是一个基准测试的环境。