Пишу, по большей части, про историю, свою жизнь и немного про программирование.

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

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

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

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

Вовсе нет.

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

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

13 комментариев
nixx 2013

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

Евгений Степанищев (bolknote.ru) 2013

Комментарий для nixx:

5.3, кажется.

Горбунов Олег 2013

Комментарий для Евгения Степанищева:

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

Евгений Степанищев (bolknote.ru) 2013

Комментарий для Горбунов Олег:

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

Boroda aka Hamster (fantaseour.livejournal.com) 2013

Комментарий для Евгения Степанищева:

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

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

Евгений Степанищев (bolknote.ru) 2013

Комментарий для fantaseour.livejournal.com:

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

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

jeka.ru 2013

Комментарий для Евгения Степанищева:

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

Евгений Степанищев (bolknote.ru) 2013

Комментарий для http://jeka.ru:

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

masterspammer (masterspammer.livejournal.com) 2013

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

Евгений Степанищев (bolknote.ru) 2013

Комментарий для masterspammer.livejournal.com:

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

masterspammer (masterspammer.livejournal.com) 2013

Комментарий для Евгения Степанищева:

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

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

kuku 2013

Комментарий для Евгения Степанищева:

но тормозило другое — цикл перебора массива объектов с выводом свойств объектов третьей вложенности

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

Евгений Степанищев (bolknote.ru) 2013

Комментарий для kuku:

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