Ассоциативный массив против SplObjectStorage

Я работаю над кодом для управления коллекцией уникальных объектов. Первый прототип этого кода использует ассоциативный массив, в основном так, как я всегда это делал.

Тем не менее, я также заинтересован в том, чтобы использовать функциональные возможности, которые были добавлены в более современные версии PHP, такие как [SplObjectStorage][1], вместо этого, отчасти в качестве учебного опыта, отчасти потому, что это обязательно дает преимущества (тесты, которые я видел, показывают, что SplObjectStorage во многих случаях может быть быстрее, чем массивы).

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

Большая проблема, которую я вижу с SplObjectStorage, заключается в том, что он (на первый взгляд) не поддерживает поведение ассоциативного массива ключ/значение и может рассматриваться только как индексированный массив. Однако документация по новым возможностям PHP не соответствует стандартам документации по более устоявшимся частям языка, и я мог просто что-то упустить.

Могу ли я использовать SplObjectStorage вместо ассоциативного массива? Если да, то как определить ключ при добавлении нового объекта? Что еще более важно, каковы относительные преимущества и недостатки SplObjectStorage по сравнению с ассоциативными массивами?


person GordonM    schedule 15.12.2011    source источник
comment
@ajreal: я не думаю, что мой вопрос так уж похож на тот, который вы указали.   -  person GordonM    schedule 15.12.2011
comment
Присмотрелся повнимательнее, но все еще не понимаю, почему моя проблема (Можете ли вы использовать SplObjectStorage вместо ассоциативного массива, и если да, то каковы преимущества и недостатки?) является дубликатом этой ( Почему я не могу поместить строки в SplObjectStorage?)   -  person GordonM    schedule 16.12.2011
comment
Я думаю, что в вопросе было предложено, если вы хотите связать массив, затем использовать хэш объекта spl и прикрепить к объекту хранилища spl. Недостаток? хлопотно. Преимущества объекта хранения spl заключаются в том, что он использует ключ индекса (см. Реализация использует только следующий, предыдущий для продвижения указателя). И возвращение к связанному ключу - это просто поражение цели. Вот что я думаю.   -  person ajreal    schedule 16.12.2011


Ответы (3)


Вы не должны рассматривать SplObjectStorage как хранилище ключей и значений, а просто набор объектов. Есть что-то в наборе или нет, но его позиция не важна.

«Ключ» элемента в SplObjectStorage на самом деле является хешем объекта. Это делает невозможным добавление нескольких копий одного и того же экземпляра объекта в SplObjectStorage, поэтому вам не нужно проверять, существует ли уже копия перед добавлением.

Однако в PHP 5.4 есть новый метод getHash(), который вы можете переопределить и который будет возвращать "хэш" объекта. Это - в некотором смысле - возвращает/устанавливает ключ, чтобы вы могли разрешить его хранение в разных условиях.

Основное преимущество SplObjectStorage заключается в том, что вы получаете множество методов работы и взаимодействия с различными наборами (contains(), removeAll(), removeAllExcept() и т. д.). Его скорость немного лучше, но использование памяти хуже, чем у обычных массивов PHP.

person JayTaph    schedule 30.01.2012
comment
В моих экспериментах splObjectStorage фактически использовал меньше памяти, чем набор массивов, хранящих хэш объекта. - person Anther; 07.02.2013
comment
На самом деле я провел тест скорости, который был опубликован здесь: technosophos.com /content/php-splobjectstorage-v-arrays-redux SPLObjectStorage, по-видимому, имеет золотую середину около 10 000 DOMDocuments, после чего производительность снижается. - person Frederik Krautwald; 16.09.2013

Результаты после запуска бенчмарка с 10 000 итераций на PHP 5.6.13:

Type Time to fill Time to check Memory
SplObjectStorage 0.021285057068 0.019490000000 2131984
Array 0.021125078201 0.020912000000 1411440

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

person Roman Liukshyn    schedule 08.10.2015
comment
Разница во времени всего 3%, а не 50%? И 34% вместо 50% по памяти. - person Daniel W.; 17.12.2015
comment
@roman Пожалуйста, не могли бы вы объяснить свою математику здесь? Я имею в виду 1,5, к которым вы пришли. - person MrSunshine; 03.09.2016
comment
Учитывая ваши данные, я получаю, что массивы на 1% быстрее заполняются, на 7% медленнее проверяются и используют на 34% меньше памяти. - person user1032531; 09.03.2017
comment
Было бы неплохо увидеть статистику в PHP7. - person Tim Wißmann; 10.07.2018
comment
@ twity1337 Итак, запустите код, указанный в ссылке, на экземпляре PHP 7. - person faintsignal; 05.07.2019
comment
SplObjectStorage на самом деле намного быстрее с PHP 7.3.1, а также использует меньше памяти на основе моего теста (100 000 итераций, 13687024 против 31891536 для массива). - person Sebj; 29.08.2019

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

person John Smith    schedule 21.04.2015