О стоимости доступа к объектам в PHP

Удивительное — рядом: недавно искали с нашими админами место в коде где больше всего тормозит вывод одной страницы одного из сайтов, сделанных в недрах нашей компании в незапамятные времена.

Код был довольно запутанный, попросили меня помочь. Место я вычислил. Если его закоментировать, страница начинала выдаваться не за десятки секунд, а за единицы.

Никогда такого не видел. Как вы думаете, что тормозило? Запросы к базе? Какая-то суперматематика? Сортировка, может быть? Цикл в цикле в цикле, а там внутри что-то сложное?

Вовсе нет.

После выборки из базы, данные выкладывались в массив сложных объектов, в данном месте это было массив из почти что 500 объектов, внутри объектов лежали другие объекты, а них — ещё. Заполнение этой структуры занимало немало времени, но тормозило другое — цикл перебора массива объектов с выводом свойств объектов третьей вложенности.

В цикле не было вызвано ни одной функции (кроме htmlspecialchars), а вывод всего этого хозяйства занимал порядка десятков секунд.
8 марта 2013 13:05

nixx (инкогнито)
8 марта 2013, 17:49

А какая версия PHP? В 5.4 кажется как раз были изменения на этот счет.

Евгений Степанищев (bolknote.ru)
8 марта 2013, 18:14, ответ предназначен nixx

5.3, кажется.

Горбунов Олег (инкогнито)
8 марта 2013, 18:44, ответ предназначен Евгений Степанищев (bolknote.ru):

Я так подозреваю, что это могло тормозить из-за ленивого чтения, нет?

Евгений Степанищев (bolknote.ru)
8 марта 2013, 19:00, ответ предназначен Горбунову Олегу

Что такое «ленивое чтение»?

Boroda aka Hamster (fantaseour.livejournal.com)
8 марта 2013, 20:42, ответ предназначен Евгений Степанищев (bolknote.ru):

Я думаю, что под ленивым чтеним имелось в виду, что выбираются объекты, которые для доставания данных по -> делают селект в БД. А при этом объект как бы есть, но не дозаполнен.

А не пробовали на синтетических тестах такое повторить? Просто 500 объектов в массив и пробежаться? Что-то как-то не верится :)

Евгений Степанищев (bolknote.ru)
8 марта 2013, 21:27, ответ предназначен fantaseour.livejournal.com:

Геттеры имеются ввиду что ли? Нет, их там нет. Синтетические тесты не пробовал. А там не просто 500 объектов, там внутри объектов ещё объекты. Т.е. выглядит как-то так:

echo $A[0]->B->C;

http://jeka.ru (инкогнито)
9 марта 2013, 21:27, ответ предназначен Евгений Степанищев (bolknote.ru):

Хм.. заинтересовался, так как не встречал подобной проблемы, вроде даже похожие случаи часто встречались.
Сейчас попробовал простенький пример написать, но он отрабатывает мгновенно.
Может из-за того что у вас объекты более сложные? Но все равно не очень понятно почему такое может быть.

Евгений Степанищев (bolknote.ru)
9 марта 2013, 22:29, ответ предназначен http://jeka.ru

Да, неясно до конца. Возможно влияет ещё какой-то фактор (внутренние баги интепретатора, например), а может и правда, дело в объёме хранимых данных (результирующий HTML получился >500КБ, а это ещё далеко не все хранящиеся в объектах данные использовались).

masterspammer (masterspammer.livejournal.com)
12 марта 2013, 13:48

Нечто подобное есть и в перле и в пайтоне.
Насколько я понимаю, поля объекта лежат в хэше, откуда
извлекаются по имени, что небесплатно. Если же неповезло и вдруг
есть много полей с совпадающим хэшем, то время будет не log(n),
а побольше.

Евгений Степанищев (bolknote.ru)
12 марта 2013, 15:51, ответ предназначен masterspammer.livejournal.com:

Если будет много полей с совпадающим хешем, то тормозить будет не на извлечении, а на вставке, так как придётся пересчитать хеши.

masterspammer (masterspammer.livejournal.com)
13 марта 2013, 07:49, ответ предназначен Евгений Степанищев (bolknote.ru):

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

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

kuku (инкогнито)
5 апреля 2013, 00:33, ответ предназначен Евгений Степанищев (bolknote.ru):

но тормозило другое — цикл перебора массива объектов с выводом свойств объектов третьей вложенности
А можно пример тормозящего кода? И какое количество объектов и свойств на каждом уровне цепочки "$A[0]->B -> C"?

Евгений Степанищев (bolknote.ru)
5 апреля 2013, 06:40, ответ предназначен kuku

Простите, но совсем не хочется сейчас вспоминать в каком это проекте, искать этот кусок кода и ревизию в «гите», где он сохранился, чистить его и выкладывать. Слишком много усилий.

Ваше имя или адрес блога (можно OpenID):

Текст вашего комментария, не HTML:

Кому бы вы хотели ответить (или кликните на его аватару)