代码1:
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 . "\n"; //0.03320002555847 echo $end2 - $end1; //0.02147388458252
但这一次,使用pass by reference很慢.
代码2:
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,'xxxxx'); $begin = microtime(true); test1($x); $end1 = microtime(true); test2($x); $end2 = microtime(true); echo $end1 - $begin . "\n"; //0.024326801300049 echo $end2 - $end1; //0.037616014480591
有人可以解释为什么通过引用传递在code1中速度快但在code2中速度慢吗?
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,庞大的阵列上.您可以将其作为值传递或作为函数的引用传递.在函数内部,然后是值(test1)或引用(test2).
代码1:正在使用foreach.使用foreach,您有两个选择:迭代值或引用(Example).迭代值时,迭代将在值的副本上完成.如果迭代引用,则不会执行任何复制.
当您在test2中使用引用时,它会更快.不需要复制值.但是在test1中,您将数组作为值传递,数组将被复制.
代码2:正在使用.因为这里什么也没做.在这两种情况下.您可以从数组中访问变量和读取值.无论是引用还是副本(这要归功于PHP中的写入优化副本),这几乎是一样的.
您现在可能想知道,为什么代码2存在差异.差异不是因为for而是因为计数.如果你传递一个引用计数PHP内部创建它的副本,因为它计数需要一个副本,而不是一个引用.
阅读:Do not use PHP references by Johannes Schlüter
>空白 – 调用函数有什么区别?@H_404_14@>伯爵 – 伯爵会有所作为吗?@H_404_14@>对于 – foronly(不计数)会发生什么?@H_404_14@> Foreach – Just foreach – 甚至打破第一个元素.
每个测试都有两个版本,一个名为_copy(将数组作为副本传递给函数),另一个名为_ref(将数组作为参考传递).
并不总是这些微基准测试告诉你真相,但如果你能够隔离特定点,你可以很好地做出有根据的猜测,例如,不是因为计数产生了影响:
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,'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\n",$test,$result); } } $buffer = explode("\n",ob_get_clean()); sort($buffer); echo implode("\n",$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