В PHP ( >= 5.0) быстрее проходит ссылка?

В PHP параметры функции могут передаваться по ссылке, добавляя амперсанд к параметру в объявлении функции, например:

function foo(&$bar)
{
    // ...
}

Теперь я знаю, что это not, предназначенное для повышения производительности, но позволяющее функциям изменять переменные, которые обычно выходят из их области.

Вместо этого PHP, похоже, использует Copy On Write, чтобы избежать копирования объектов (а может быть и массивов) до тех пор, пока они не будут изменены. Таким образом, для функций, которые не изменяют свои параметры, эффект должен быть таким же, как если бы вы передали их по ссылке.

Тем не менее, мне было интересно, может ли логика "Копировать по записи" коротко обрезать по ссылке на ссылку и влияет ли это на производительность.

ETA: Конечно, я предполагаю, что это не быстрее, и я хорошо знаю, что это не то, что ссылки для. Поэтому я думаю, что мои собственные догадки неплохие, я просто ищу ответ от кого-то, кто действительно знает, что конкретно происходит под капотом. За пять лет разработки PHP мне всегда было трудно получить качественную информацию о внутренних функциях PHP, не считая источник.

Ответ 1

Zend Engine использует copy-on-write, и когда вы используете ссылку самостоятельно, она берет немного дополнительных накладных расходов. Можно найти это упоминание в момент написания, и комментарии в руководство содержат другие ссылки.

(EDIT) На странице руководства Объекты и ссылки содержится немного больше информации о том, как переменные объекта отличаются от ссылок.

Ответ 2

В тесте с 100 000 итерациями вызова функции со строкой 20 кБ результаты:

Функция, которая просто считывает/использует параметр

pass by value:      0.12065005 seconds
pass by reference:  1.52171397 seconds

Функция для записи/изменения параметра

pass by value:      1.52223396 seconds
pass by reference:  1.52388787 seconds

Выводы

  • Передача параметра по значению всегда быстрее

  • Если функция изменяет значение переданной переменной, для практических целей это то же самое, что передавать по ссылке, чем по значению

Ответ 3

Я провел некоторое испытание на этом, потому что я был не уверен в ответах.

Мои результаты показывают, что передача больших массивов или строк по ссылке IS значительно быстрее.

Вот мои результаты: Benchmark

Ось Y (Runs) - сколько раз функция могла быть вызвана за 1 секунду * 10

Тест повторялся 8 раз для каждой функции/переменной

И вот переменные, которые я использовал:

$large_array = array_fill(PHP_INT_MAX / 2, 1000, 'a');
$small_array = array('this', 'is', 'a', 'small', 'array');
$large_object = (object)$large_array;
$large_string = str_repeat('a', 100000);
$small_string = 'this is a small string';
$value = PHP_INT_MAX / 2;

Это следующие функции:

function pass_by_ref(&$var) {
}

function pass_by_val($var) {
}

Ответ 4

Я уверен, что нет, это не быстрее. Кроме того, в руководстве конкретно говорится о том, чтобы не использовать ссылки для повышения производительности.

Изменить: Не могу найти, где он говорит, но он там!

Ответ 5

Я экспериментировал со значениями и ссылками строки длиной 10 килобайт, передавая ее двум идентичным функциям. Один принимает аргумент по значению, а второй - по ссылке. Они были общими функциями - принимать аргументы, выполнять простую обработку и возвращать значение. Я сделал 100 000 звонков обоих и выяснил, что ссылки не предназначены для повышения производительности - прибыль от ссылки составляет около 4-5%, и она растет только тогда, когда строка становится достаточно большой (100 тыс. И более, что дает улучшение на 6-7%), Итак, мой вывод не использует ссылки для увеличения производительности, этот материал не для этого.

Я использовал PHP Version 5.3.1

Ответ 6

Нет ничего лучше тестового фрагмента кода

<?PHP
$r = array();

for($i=0; $i<500;$i++){
$r[]=5;
}

function a($r){
$r[0]=1;
}
function b(&$r){
$r[0]=1;
}

$start = microtime(true);
for($i=0;$i<9999;$i++){
  //a($r);
  b($r);
}
$end = microtime(true);

echo $end-$start;
?>

Конечный результат! Чем больше массив (или чем больше количество вызовов), тем больше разница. Поэтому в этом случае вызов по ссылке быстрее, потому что значение изменяется внутри функции.

В противном случае нет реальной разницы между "по ссылке" и "по значению", компилятор достаточно умен, чтобы не создавать новую копию каждый раз, если нет необходимости.

Ответ 7

При передаче объектов нет необходимости добавлять и выполнять оператор. В PHP 5+ объекты все равно передаются по ссылке.