Я думал, что если $v
не изменится [foreach($a as $v)
], реального копирования не произойдет из-за копирования при записи , но почему это быстро, когда передается по ссылке?
Воздействие не на $v
, а на $a
, огромный массив. Вы или передаете его как значение или как ссылку на функцию. Внутри функции это значение (test1) или ссылка (test2).
У вас есть два кода (код 1 и код 2).
Код 1: Используется foreach
. С foreach
у вас есть два варианта: перебрать значение или ссылку ( Пример ). Когда вы выполняете итерацию по значению, итерация выполняется для копии значения. Если вы перебираете ссылку, копирование не производится.
Поскольку вы используете ссылку в test2, это быстрее. Значения не нужно копировать. Но в test1 вы передаете массив как значение, массив копируется.
Код 2: Используется for
. Ибо здесь ничего не происходит. В обоих случаях. Вы получаете доступ к переменной и читаете значение из массива. Это в значительной степени одинаково, независимо от того, является ли это ссылкой или копией (благодаря оптимизации copy при записи в PHP).
Теперь вы можете задаться вопросом, почему является разницей в коде 2. Разница не в for
, а в count
. Если вы передаете ссылку на count
, PHP внутренне создает ее копию, потому что count
нужна копия, а не ссылка.
Читайте также: Не используйте ссылки PHP от Johannes Schlüter
Я также собрал набор тестов. Но я более конкретно помещаю код в тестовые функции.
- Пробел - какая разница в вызове функции?
- Количество -
count
имеет значение?
- Для - Что происходит только с
for
(не count
)?
- Foreach - Просто
foreach
- даже разрыв на первом элементе.
Каждый тест представлен в двух версиях: одна называется _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\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