English 中文(简体)
php foreach, 这就是为什么利用阵列的通行证的速度快?
原标题:php foreach, why using pass by reference of a array is fast?

下面是大型阵列每一座椅子的试验,我认为,如果<代码>v, 真正的复制不会因为copy on letter而发生,但为什么在通过参考时会很快?

<><><>>

function test1($a){
  $c = 0;
  foreach($a as $v){ if($v== xxxxx ) ++$c; }
}

function test2(&$a){
  $c = 0;
  foreach($a as $v){ if($v== xxxxx ) ++$c; }
}

$x = array_fill(0, 100000,  xxxxx );

$begin = microtime(true);
test1($x);
$end1 = microtime(true);
test2($x);
$end2 = microtime(true);

echo $end1 - $begin . "
";   //0.03320002555847
echo $end2 - $end1;           //0.02147388458252

但这一次,使用通行证是缓慢的。

<><>><>>>>

function test1($a){
  $cnt = count($a); $c = 0;
  for($i=0; $i<$cnt; ++$i)
    if($a[$i]== xxxxx ) ++$c;
}
function test2(&$a){
  $cnt = count($a); $c = 0;
  for($i=0; $i<$cnt; ++$i)
    if($a[$i]== xxxxx ) ++$c;
}
$x = array_fill(0, 100000,  xxxxx );

$begin = microtime(true);
test1($x);
$end1 = microtime(true);
test2($x);
$end2 = microtime(true);

echo $end1 - $begin . "
";   //0.024326801300049
echo $end2 - $end1;           //0.037616014480591

是否有人解释为什么在法典1中迅速通过参考,但守则2进展缓慢?

Edit: With Code 2, the count($a) makes the main difference, so the time of the loop took is almost the same.

最佳回答

I thought that if the $v don t change [foreach($a as $v)], the real copy will not happen because of copy on write, but why it is fast when pass by reference?

影响不在于<代码>v,而在于$a,即巨大的阵容。 您要么将它作为价值,要么作为职能参考。 在职能部分,它的价值(测试1)或参照(测试2)。

你有两部法典(第1条和第2条)。

<><><>> 采用<代码>foreach。 页: 1 当贵重时,则在价值copy上填满。 如果你重复提及,就没有复制件。

由于你在测试2中使用这一提法,其速度更快。 这些价值观无需复制。 但是,在试验1中,你通过阵列作为价值,阵列被复制。

<><>><>>>> 采用<条码>。 这里实际上没有任何东西。 在这两种情况下。 你们能够从阵列中获得变数和读值。 即便有参考书或复制件(参见copy on letter Bestation in PHP),这还是完全一样。

您现在可能想知道,为什么有is的代码差异。 2. 差异不是因为<条码>至,而是因为<条码>。 请注意<代码>。 PHP内部制作一份复印件,因为它需要一份复印件,而不是参考。

阅读: rel=“noreferer”>。 Do not use PHP reference by Johannes Schlüter


我还汇编了一套测试。 但我更具体地将守则纳入测试职能。

  • Blank - What s the difference in calling the function?
  • Count - Does count make a difference?
  • For - What happens with foronly (not count)?
  • Foreach - Just foreach - even breaking on first element.

每一次测试均分两种版本,一个称为_copy。 (将阵列作为复制件并入功能)和一份称为<代码>_ref (参照阵列)。

并不总是这些缩微标语告诉你真相,但如果你能够孤立具体要点,你就可以很好地做受过教育的猜测,例如,没有<<<<>for>但count。 影响:

function blank_copy($a){
}
function blank_ref(&$a){
}
function foreach_copy($a){
    foreach($a as $v) break;
}
function foreach_ref(&$a){
    foreach($a as $v) break;
}
function count_copy($a){
  $cnt = count($a);
}
function count_ref(&$a){
  $cnt = count($a);
}
function for_copy($a){
    for($i=0;$i<100000;$i++)
        $a[$i];
}
function for_ref(&$a){
    for($i=0;$i<100000;$i++)
        $a[$i];
}

$tests = array( blank_copy ,  blank_ref ,  foreach_copy ,  foreach_ref ,  count_copy ,  count_ref ,  for_copy ,  for_ref );


$x = array_fill(0, 100000,  xxxxx );
$count = count($x);
$runs = 10;

ob_start();

for($i=0;$i<10;$i++)
{
    shuffle($tests);
    foreach($tests as $test)
    {
        $begin = microtime(true);
        for($r=0;$r<$runs;$r++)
            $test($x);
        $end = microtime(true);
        $result = $end - $begin;
        printf("* % .-16s: %f
", $test, $result);
    }
}

$buffer = explode("
", ob_get_clean());
sort($buffer);
echo implode("
", $buffer);

产出:

* blank_copy......: 0.000011
* blank_copy......: 0.000011
* blank_copy......: 0.000012
* blank_copy......: 0.000012
* blank_copy......: 0.000012
* blank_copy......: 0.000015
* blank_copy......: 0.000015
* blank_copy......: 0.000015
* blank_copy......: 0.000015
* blank_copy......: 0.000020
* blank_ref.......: 0.000012
* blank_ref.......: 0.000012
* blank_ref.......: 0.000014
* blank_ref.......: 0.000014
* blank_ref.......: 0.000014
* blank_ref.......: 0.000014
* blank_ref.......: 0.000015
* blank_ref.......: 0.000015
* blank_ref.......: 0.000015
* blank_ref.......: 0.000015
* count_copy......: 0.000020
* count_copy......: 0.000022
* count_copy......: 0.000022
* count_copy......: 0.000023
* count_copy......: 0.000024
* count_copy......: 0.000025
* count_copy......: 0.000025
* count_copy......: 0.000025
* count_copy......: 0.000026
* count_copy......: 0.000031
* count_ref.......: 0.113634
* count_ref.......: 0.114165
* count_ref.......: 0.114390
* count_ref.......: 0.114878
* count_ref.......: 0.114923
* count_ref.......: 0.115106
* count_ref.......: 0.116698
* count_ref.......: 0.118077
* count_ref.......: 0.118197
* count_ref.......: 0.123201
* for_copy........: 0.190837
* for_copy........: 0.191883
* for_copy........: 0.193080
* for_copy........: 0.194947
* for_copy........: 0.195045
* for_copy........: 0.195944
* for_copy........: 0.198314
* for_copy........: 0.198878
* for_copy........: 0.200016
* for_copy........: 0.227953
* for_ref.........: 0.191918
* for_ref.........: 0.194227
* for_ref.........: 0.195952
* for_ref.........: 0.196045
* for_ref.........: 0.197392
* for_ref.........: 0.197730
* for_ref.........: 0.201936
* for_ref.........: 0.207102
* for_ref.........: 0.208017
* for_ref.........: 0.217156
* foreach_copy....: 0.111968
* foreach_copy....: 0.113224
* foreach_copy....: 0.113574
* foreach_copy....: 0.113575
* foreach_copy....: 0.113879
* foreach_copy....: 0.113959
* foreach_copy....: 0.114194
* foreach_copy....: 0.114450
* foreach_copy....: 0.114610
* foreach_copy....: 0.118020
* foreach_ref.....: 0.000015
* foreach_ref.....: 0.000016
* foreach_ref.....: 0.000016
* foreach_ref.....: 0.000016
* foreach_ref.....: 0.000018
* foreach_ref.....: 0.000019
* foreach_ref.....: 0.000019
* foreach_ref.....: 0.000019
* foreach_ref.....: 0.000019
* foreach_ref.....: 0.000020
问题回答

实际上,我不同意第一个答案。 最重要的是,正如评论所言,测试并不相同。 这里是经过全异构体测试的,仅对 lo进行检测。

第1版

<?php
function test1($a) {
    $c = 0;
    $begin = microtime(true);
    foreach ($a as $v) {
        if ($v ==  x ) ++$c;
    }
    $end = microtime(true);
    echo $end - $begin . "
";
    return $c;
}

function test2(&$a) {
    $c = 0;
    $begin = microtime(true);
    foreach ($a as $v) {
        if ($v ==  x ) ++$c;
    }
    $end = microtime(true);
    echo $end - $begin . "
";
    return $c;
}

$x = array_fill(0, 1000000,  x );

test1($x); // 0.11617302894592
test2($x); // 0.059789180755615

第2版

<?php
function test1($a) {
    $cnt = count($a);
    $c = 0;
    $begin = microtime(true);
    for ($i = 0; $i < $cnt; ++$i) if ($a[$i] ==  x ) ++$c;
    $end = microtime(true);
    echo $end - $begin . "
";
    return $c;
}

function test2(&$a) {
    $cnt = count($a);
    $c = 0;
    $begin = microtime(true);
    for ($i = 0; $i < $cnt; ++$i) if ($a[$i] ==  x ) ++$c;
    $end = microtime(true);
    echo $end - $begin . "
";
    return $c;
}

$x = array_fill(0, 1000000,  x );

test1($x); // 0.086347818374634
test2($x); // 0.086491107940674

通知说,在全异构体形式中,第二次测试显示不存在差异,而第一次测试则表明了这一点。 为什么?

The answer is that the array has an internal pointer for things like foreach. It can be accessed by calls like current. When you do foreach with a reference, the original array s pointers is used. When you pass by value, the array internals must be copied as soon as the foreach executes, even if the values are maintained somehow by the engine. Thus, the penalty.





相关问题
Brute-force/DoS prevention in PHP [closed]

I am trying to write a script to prevent brute-force login attempts in a website I m building. The logic goes something like this: User sends login information. Check if username and password is ...

please can anyone check this while loop and if condition

<?php $con=mysql_connect("localhost","mts","mts"); if(!con) { die( unable to connect . mysql_error()); } mysql_select_db("mts",$con); /* date_default_timezone_set ("Asia/Calcutta"); $date = ...

定值美元

如何确认来自正确来源的数字。

Generating a drop down list of timezones with PHP

Most sites need some way to show the dates on the site in the users preferred timezone. Below are two lists that I found and then one method using the built in PHP DateTime class in PHP 5. I need ...

Text as watermarking in PHP

I want to create text as a watermark for an image. the water mark should have the following properties front: Impact color: white opacity: 31% Font style: regular, bold Bevel and Emboss size: 30 ...

How does php cast boolean variables?

How does php cast boolean variables? I was trying to save a boolean value to an array: $result["Users"]["is_login"] = true; but when I use debug the is_login value is blank. and when I do ...

热门标签