Форум dkLab и Denwer
Здесь общаются Web-разработчики.
Генеральный спонсор:
Хостинг «Джино»

Отложенное копирование переменных в PHP (Дмитрий Агафонов)
Author Message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Tue Jul 18, 2006 4:44 pm ()
   Post subject:
Reply with quote


М

Выделено из темы «6_DbSimple: лаконичная работа с различными СУБД»,
расположенной в форуме Конструктор (19 Июля 2006, 12:51).
Back to top
View user's profile Send private message Send e-mail
Дмитрий Агафонов
Заглянувший



Joined: 18 Jul 2006
Posts: 5
Карма: 0
   поощрить/наказать

Location: Саратов

PostPosted: Tue Jul 18, 2006 4:44 pm (спустя 1 секунду; написано за 12 минут 15 секунд)
   Post subject:
Reply with quote

Дмитрий Котеров wrote:
Гость wrote:
$xxx['parentNode']=&$parent;
Мне это сильно не нравится: ссылки - зло.

Какую именно задачу Вы решаете, что нужно искать PID?
Я почти согласен про зло.
Но работать по ссылкам в функциях, манипулирующих данными на мой взгляд правильнее, т.е.
Code (php): скопировать код в буфер обмена
function process($s) {
 //
 return $s;
}
$string = process($string);

// VS

function process(&$s) {
 //
 return $if_was_error;
}
$error = process($string);
Особенно при манипуляциях с большими объемами - десятки и сотни килобайт и сложными массивами и объектами.
При большой нагрузке на сервер все эти операции с памятью на создание экземпляров переменных дадут прикурить...

к стати foreach тоже создает копию при пробегании по массиву, т.е. исправить элемент массива так низя :(

Какую задачу, спрашиваете? Как и все - CMS :)
Навигация по структуре сайта выгруженную методом $DB->selectTree();
Для поиска соответствий и манипуляций с данными...
Back to top
View user's profile Send private message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Wed Jul 19, 2006 8:55 am (спустя 16 часов 10 минут; написано за 2 минуты 29 секунд)
   Post subject:
Reply with quote

Дмитрий Агафонов wrote:
При большой нагрузке на сервер все эти операции с памятью на создание экземпляров переменных дадут прикурить...
к стати foreach тоже создает копию при пробегании по массиву, т.е. исправить элемент массива так низя :(
Вы ошибаетесь насчет скорости. В ряде случаев параметры-ссылки работают медленее, чем параметры-зачения. Читайте про то, как PHP оптимизирует операцию присваивания (копирование при изменении), либо поищите тут в форуме - кажется, куски публиковались. Впрочем, это все оффтопик, так что завязываем с ним.
Дмитрий Агафонов wrote:
Какую задачу, спрашиваете? Как и все - CMS :)
Как правильно задавать вопросы: статья, обязательная к прочтению (citforum.ru/howto/smart-questions-ru.shtml)
Интересует задача более низкого уровня, для которой нужны ссылки от потомков к родителям. Вероятнее всего, ее можно решить другим способом.
Back to top
View user's profile Send private message Send e-mail
Дмитрий Агафонов
Заглянувший



Joined: 18 Jul 2006
Posts: 5
Карма: 0
   поощрить/наказать

Location: Саратов

PostPosted: Wed Jul 19, 2006 10:00 am (спустя 1 час 4 минуты; написано за 4 минуты 25 секунд)
   Post subject:
Reply with quote

Дмитрий Котеров wrote:
Дмитрий Агафонов wrote:
При большой нагрузке на сервер все эти операции с памятью на создание экземпляров переменных дадут прикурить...
к стати foreach тоже создает копию при пробегании по массиву, т.е. исправить элемент массива так низя :(
Вы ошибаетесь насчет скорости. В ряде случаев параметры-ссылки работают медленее, чем параметры-зачения. Читайте про то, как PHP оптимизирует операцию присваивания (копирование при изменении), либо поищите тут в форуме - кажется, куски публиковались. Впрочем, это все оффтопик, так что завязываем с ним.
Я нашел только вот: php.spb.ru/php/speed.html

В любом случае завязываю, спасибо за ответы и DBSimple.
Back to top
View user's profile Send private message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Wed Jul 19, 2006 12:53 pm (спустя 2 часа 53 минуты; написано за 58 секунд)
   Post subject:
Reply with quote

Технология отложенного копирования
На первый взгляд кажется, что передача параметров в функцию по ссылке (с использованием &) должна работать с большей скоростью, нежели передача по значению (без &). На практике же утверждение оказывается не соответствующим действительности: искусственное добавление амперсанда перед именем аргумента не увеличивает скорость работы программы!

Прежде, чем разъяснять эту в высшей степени странную ситуацию, давайте проведем небольшой эксперимент — запустим скрипт из листинга 14.19, который сравнивает скорость работы разных видов функций.
Листинг 14.19. Файл speed.php
Code (php): скопировать код в буфер обмена
<?php #
//
function takeVal($a) { $x = $a[1234]; }
//
function takeRef(&$a) { $x = $a[1234]; }
//
function takeValAndModif($a) { $a[1234]++; }
//
function takeRefAndModif(&$a) { $a[1234]++; }

//
test("takeVal");
test("takeRef");
test("takeValAndModif");
test("takeRefAndModif");

function test($func) {
   //
   $a = array (www.php.net/array)();
   for ($i=1; $i<=100000; $i++) $a[$i] = $i;
   //
   for ($t=time (www.php.net/time)(); $t == time (www.php.net/time)(); );
   //
   for ($N=0, $t=time (www.php.net/time)(); time (www.php.net/time)() == $t; $N++) $func($a);
   printf (www.php.net/printf)("<tt>$func</tt> took %d itr/sec<br>", $N);
}
?>
Суть теста заключается в том, что мы создаем в памяти массив очень большого раз-мера (100000 элементов) и передаем его в функции с разными видами параметров, замеряя при этом время работы. В конце выводится сводка, сколько вызовов функ-ций разного типов "уложилось" ровно в 1 секунду.
Результаты довольно интересны, вот они (процессор Intel Centrino Dothan, 1.8 GHz):
Code (any language): скопировать код в буфер обмена
takeVal took 290323 itr/sec
takeRef took 286337 itr/sec
takeValAndModif took 14 itr/sec
takeRefAndModif took 236021 itr/sec
Давайте посмотрим вначале на первые две строчки. Он говорят, что вызов функции с передачей параметра по значению работает даже быстрее, чем передача по ссылке! В действительности, запустив тест несколько раз подряд, можно убедиться, что раз-ница в скорости не выходит за рамки погрешности подсчета времени: иногда takeRef() выходит на первое место по сравнению с takeVal(), а иногда (вот как сейчас) — на второе.
Для того чтобы понять, каким же образом передача параметров по значению может работать не медленнее, чем по ссылке, взглянем на третью и четвертую строки ре-зультата. Вы видите, что функция takeValAndModif(), принимающая аргумент по значению и изменяющая его "локальную копию", резко (примерно в двадцать тысяч раз!) медленнее, чем ее аналог, имеющий агрумент-ссылку! Но ведь только что мы говорили, что параметры-ссылки и параметры-значения не различаются сколько-нибудь существенно по скорости. Что же происходит?
Ответ кроется в одной особенности языка PHP версий 4 и 5, которые авторы этой книги не встречали ни в одном другом языке программирования. Речь идет о техно-логии отложенного копирования данных. Она работает так: когда в программе вы-полняется оператор присваивания (или, что то же самое, передача параметра в функ-цию по значению), PHP никуда не копирует данные, содержащиеся в переменной (в нашем случае — огромный массив). Вместо этого он просто помечает переменную-приемник как копию источника, что практически не отнимает времени. Реальное копирование данных будет отложено до того момента, когда одна из переменных потребует изменения (в примере выше — инкремент одной ячейки массива).
Таким образом, если вы в программе делаете сто "копий" одной и той же перемен-ной при помощи оператора присваивания, а потом меняете только одну из них, PHP в реальности произведет всего лишь одну операцию копирования (а не сто, как это сделали бы другие языки программирования: PHP3, Perl, C++ и т.д.). Разработчики PHP мудро учли тот факт, что в крупных программах большинство операций копи-рования носят характер абстрактного "переименования" и производятся "вхоло-стую", а значит, в идеале не требуют передачи больших блоков данных и выделения новой памяти.
Теперь вы понимаете, почему функция takeValAndModif() оказалась в 20000 раз медленнее, чем takeRefAndModif(), а takeVal() и takeRef() работают с одинако-вой скоростью? Ведь медленная функция изменяет свой параметр-значение, что за-ставляет PHP немедленно породить локальную копию переменной, уничтожаемую после выхода из функции. В то же время, изменение параметра-ссылки в takeRe-fAndModif() не влечет копирование, ибо модификация производится в уже сущест-вующем массиве. Что касается takeVal(), то она свой параметр не изменяет, и по-тому копирования и связанной с ним потери производительности нет.
Back to top
View user's profile Send private message Send e-mail
Константин Жинько [tIT]
Сотрудник «Лаборатории»



Joined: 12 Jun 2004
Posts: 2264
Карма: 106
   поощрить/наказать

Location: Москва

PostPosted: Thu Jul 20, 2006 9:14 am (спустя 20 часов 20 минут; написано за 2 минуты 20 секунд)
   Post subject:
Reply with quote

У меня почти в 1.4 раза больше (AMD 64 Athlon 3200+ (2GHz) + 1024 MB DDR400 + Apache 2.0.54 + PHP 5.1.4):
Quote:
takeVal took 384498 itr/sec
takeRef took 381845 itr/sec
takeValAndModif took 12 itr/sec
takeRefAndModif took 325136 itr/sec
Вот и верь железу после этого %)
Back to top
View user's profile Send private message
Maus
Модератор



Joined: 29 Jun 2003
Posts: 8151
Карма: 271
   поощрить/наказать

Location: пос. Омсукчан Магаданской области

PostPosted: Thu Jul 20, 2006 10:09 am (спустя 55 минут; написано за 2 минуты 18 секунд)
   Post subject:
Reply with quote

Еще чуток статистики: Cel 2.26GHz, 752Mb RAM, Apache/1.3.33 (Win32) PHP/4.4.2.2 (брал со snaps.php.net в начале июля вроде бы )
Quote:
takeVal took 20729 itr/sec
takeRef took 20515 itr/sec
takeValAndModif took 8 itr/sec
takeRefAndModif took 22773 itr/sec
Меньше раз в 15
Back to top
View user's profile Send private message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Thu Jul 20, 2006 1:56 pm (спустя 3 часа 46 минут; написано за 33 секунды)
   Post subject:
Reply with quote


М

Слушайте, ну это же все оффтопик. При чем тут конкретные цифры? Надо смотреть на отношение этих цифр между собой.
Back to top
View user's profile Send private message Send e-mail
Дмитрий Агафонов
Заглянувший



Joined: 18 Jul 2006
Posts: 5
Карма: 0
   поощрить/наказать

Location: Саратов

PostPosted: Thu Jul 20, 2006 10:06 pm (спустя 8 часов 9 минут; написано за 3 минуты 59 секунд)
   Post subject: Оптимизация кода вообщем
Reply with quote

К стати, а вот если эти все моменты собрать в виде cook-book - такие конструкции надо писать так-то, ибо даже простая проверка показывает, что...
У многих, даже не один год пишущих программы, нет времени проверить все моменты, так хотябы узнают правду :)
Вот ссылка, которую я давал выше, она про то, хотя уже старенькая. Наверное есть уже наработки про объектое программирование и прочее.
В идеале - можно даже оптимизатор написать, но это из области фантастики...
Back to top
View user's profile Send private message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Tue Jul 25, 2006 10:59 am (спустя 4 дня 12 часов 53 минуты; написано за 1 минуту 11 секунд)
   Post subject:
Reply with quote

Ссылка, которую Вы давали выше, прекрасный пример экономии на спичках, и в реальной практике она совершенно бесполезна. Любой substr(), проскочивший в программе, даст нагрузку в 100 раз бОльшую, чем разница, которую Вы сможете ощутить, заменив "aa $b cc" на "aa" . $b . "cc". А читабельность снизится.
Back to top
View user's profile Send private message Send e-mail
Dark-Demon
Участник форума
Banned


Joined: 04 Feb 2007
Posts: 45
Карма: -3
   поощрить/наказать

Location: spb

PostPosted: Sun Feb 04, 2007 1:32 pm (спустя 6 месяцев 10 дней 2 часа 33 минуты; написано за 3 минуты 51 секунду)
   Post subject:
Reply with quote

Quote:
В ряде случаев параметры-ссылки работают медленее, чем параметры-зачения.
прям чудеса в решете :) передача по значению в принципе не может быть быстрее передачи по ссылке. если у вас получается такой результат - значит что-то не так в скрипте тестирования. если конкретнее, то в использовании низкоточной функции time(). да и правильнее замерять время работы скрипта, а не число циклов за время, ибо определение текущего времени - далеко не мгновенная операция.
Code (any language): скопировать код в буфер обмена
такая замена действительно практически не влияет на скорость, поэтому двойные кавычки нужно заменить на одинарные.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic All times are GMT + 3 Hours
Page 1 of 1    Email to a Friend.
You cannot post new topics in this forum. You cannot reply to topics in this forum. You cannot edit your posts in this forum. You cannot delete your posts in this forum. You cannot vote in polls in this forum. You cannot attach files in this forum. You can download files in this forum.
XML