Передача значений по ссылкам


Передача значений по ссылкам
Отрицательная сторона передачи значений по ссылкам. Без всякой лирики, прямо: использование ссылок для передачи значений снижает производительность.
Без всякой лирики, прямо: использование ссылок для передачи значений снижает производительность. Мы думаем, что вместо того что бы передавать копию переменной, сценарий передает саму переменную, исходя из чего делаем вывод, что это должно работать быстрее. Увы, это заблуждение. Что бы понять почему давайте разберёмся с тем, как процессор Zend Engine обрабатывает значения.

При работе с переменными процессор Zend Engine реализует систему значений с подсчётом ссылок, копировании при записи. Это означает, что многие переменные могут указывать на одно и то же значение. При этом большое количество блоков памяти не потребляется. Рассмотрим пример:

  1. <?php
  2.  $a = array(1, 2, 3, 4, 5);
  3.  $b = $a;
  4. ?>

Переменной $b присваивается значение переменной $a, при этом сами данные никуда не копируются! Вместо этого переменная $b преобразуется таким образом, что бы указывать на тоже место в памяти, где хранится переменная $a, т. е. на место хранения первоначально присвоенных данных (в нашем случае это массив со значениями). Процессор отмечает массив и увеличивает счётчик ссылок до 2-х. Рассмотрим ещё один пример:

  1. <?php
  2.  $a = array(1, 2, 3, 4, 5);
  3.   $b = $a;
  4.  $a[] = 6;
  5.  print_r($a);
  6.  print_r($b);
  7. ?>

Надеюсь, никто не ждал, что значение переменных окажется одинаковым? :) Шутка. Так что же произошло, если мы тут говорили о ссылках на одно место в памяти? Когда мы начали производить модификацию массива процессор Zend Engine разделяет версии $a и $b. Как только процессор обнаруживает операцию записи по значению, на которую имеется более одной ссылки, происходит копирование данных — создаётся идентичное значение, расположенное в другом участке памяти, никак не связанным с любой другой ссылкой. И только после того как этап копирования при записи будет пройден операция будет продолжена. Такое своевременное дублирование повышает производительность без каких-либо побочных эффектов. И все благодаря исключению копирования ненужных данных!

Однако, все вышесказанное не дает ответа на вопрос «почему же передача по ссылке — зло?».

Во-первых, это бесполезно, т. к. благодаря механизму подсчёта ссылок нет необходимости в передаче переменных по ссылке. Процессор сам будет избегать ненужного копирования при малейшей возможности.

Во-вторых, процессор… так, давайте-ка лучше разберем на примере. Добавим к нашему коду функцию распечатки содержимого:

  1. <?php
  2.  function prepareArr(&$arr) {
  3.   print count($arr) * 2;
  4.  }
  5.  $a = array(1, 2, 3, 4, 5);
  6.  $b = $a;
  7.  prepareArr($a);
  8. ?>

Когда процессор приступает к передаче массива $a в функции prepareArr(), он определяет, что значение (наш массив) необходимо передавать по ссылке. Далее обнаруживает, что счётчик ссылок больше 1 (в нашем случае он равен 2). Поскольку значение массива $a передается по ссылке и любые изменения, которые может внести в него наша функция, никак не должны отразиться на $b, процессор делает отдельные копии для массивов $a и $b. При передаче значения переменной в функцию Zeng Engine может просто нарастить счётчик ссылок.

Нанооптимизация, подумаете вы? Может быть, но при передаче значений по ссылке вы теряете 30% производительности этой операции. И чем больше объем данных, с которыми вы работаете, тем больше падает скорость выполнения операции.

Например, выполнение последнего примера в цикле из 50000 итераций составит 0.4538291 сек. Этот же скрипт, но без использования ссылок выполняется за 0.3090010 сек., т. е. на 30% быстрее. Если увеличить объем данных до 6,5 кб, то выполнение циклов с 5000 итераций составим 19.7765129 сек. и 7.3865049 сек. соответственно. Последняя цифра, как вы уже сами догадались, результат выполнения функции без использования ссылок.

В ключе повышения производительности не рекомендуется использовать передачу значений по ссылке. Использование ссылок оправдано только тогда, когда это имеет смысл с функциональной точки зрения.

© habrahabr, автор: iBear

Оценить Статью:  
1   2   3   4   5   6   7   8   9   10    

« Назад
SAPE все усложнил?

MainLink - простая и прибыльная продажа ссылок!

Последние поступления:

Размещена 10 августа 2020 года

Я по ТВ видел, что через 10 лет мы будем жить лучше, чем в Германии...
Я не понял, что это они с Германией сделать хотят?!

читать далее…

ТехЗадание на Землю

Размещена 14 марта 2018 года

Пpоект Genesis (из коpпоpативной пеpеписки)

читать далее…

Шпаргалка по работе с Vim

Размещена 05 декабря 2017 года

Vim довольно мощный редактор, но работа с ним не всегда наглядна.
Например если нужно отредактировать какой-то файл например при помощи crontab, без знания специфики работы с viv никак.

читать далее…

Ошибка: Error: Cannot find a valid baseurl for repo

Размещена 13 сентабря 2017 года

Если возникает ошибка на centos 5 вида
YumRepo Error: All mirror URLs are not using ftp, http[s] or file.
Eg. Invalid release/

читать далее…

Linux Optimization

Размещена 30 июля 2012 года

Prelink

читать далее…