Кэш-объект в PHP без использования сериализации

У меня есть сложный объект, который я создаю в PHP script. Я ищу способ сохранить этот объект таким образом, чтобы последующие запросы не нуждались в его воссоздании, или тратили время на неэтериализацию и перестройку. Используя xdebug, я обнаружил, что потратил половину всего времени запроса на создание этого объекта. Даже когда я храню объект явно в APC (или memcache), время его неэтериализации и загрузки всех классов занимает почти столько же времени, сколько и создание объекта.

Я не знаю, можно ли хранить и затем загружать "скомпилированный" объект в PHP. Это возможно? Существуют ли другие решения?

Я не уверен, что это возможно, но я думал, что должен спросить об этом.

EDIT: объект является двоичным деревом и используется как дерево решений. Код - это, в основном, API, который необходим для быстрого возврата ответа от дерева. Все это должно постоянно возрастать, поэтому я стараюсь максимизировать производительность везде, где это возможно.

Ответ 1

Насколько я знаю, невозможно кэшировать объекты в PHP без сериализации. В общем, однако, механизмы кэширования (APC, Memcache и т.д.) Действительно пытаются удалить соединения (-ы) db более, чем улучшить производительность (и тем самым уменьшить общую нагрузку DB). Это определенно, как memcache и другие работают в отношении Drupal. Другими словами, механизмы кэширования должны позволить вам масштабировать, хотя они могут не особенно улучшить производительность.
Реализация механизма кэширования должна позволять вам более легко масштабироваться наружу, даже если производительность на машину не лучше, чем раньше для одного соединения. При определенном пороге производительность БД резко ухудшится, и механизмы кэширования должны помочь смягчить эту проблему.

Ответ 2

Посмотрите на Igbinary расширение PHP. Это замена для сериализации и нессериализации, и это может удовлетворить ваши потребности.

Он хранит объекты в двоичном формате вместо строки, которая уменьшает использование памяти, а также уменьшает время для сериализации и несериализации объектов.

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

Ответ 3

Возможно, решение состоит в том, чтобы не построить один, массивный, дорогой объект.

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

Ответ 4

igBinary - полезное расширение, которое может помочь вам добиться более быстрого процесса сериализации/несериализации. Он заменяет стандартный механизм сериализации более умным, двоичным. Если вы управляете своим собственным сервером и можете его установить, стоит попробовать.

Ответ 5

НЕТ, невозможно сохранить объект PHP в несериализованной форме; по крайней мере, не со следующими кэширующими решениями (я пробовал эти, не знаю о других, которые могут существовать):

  • файлы
  • Memcached
  • APC
  • База данных (да, вы можете думать о кешировании вещей в DB ^^ Drupal делает это по умолчанию, например)

Если для удаления вашего объекта требуется много времени, возможно, это действительно большой? Есть ли способ уменьшить размер?

Например, у вас есть большой кусок кода HTML в этом объекте? Если да, может ли он быть сохранен в другой записи кэша?
(сериализация - это "преобразование некоторых данных в строку, поэтому, если вы уже работаете со строкой, вам не нужно повторно сериализовать ее для хранения в кеше"

Или, может быть, это не займет много времени, чтобы создать его с нуля? В этом случае действительно ли кэширование необходимо?

Ответ 6

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

Ответ 7

в этом случае лучшим вариантом будет создание собственного сервера.

он легко выполним в php - и у вас уже есть код - но php не может быть первым выбором большинства, когда дело доходит до написания серверов.

  • это может стать новым узким местом вашего приложения (поскольку php на самом деле не готов к многопоточности и запросы на запросы последовательно)
  • не все хостеры позволяют создавать собственные скрипты cli
  • Если ваше дерево решений изменяется, вы должны уведомить свой сервер о восстановлении дерева

Ответ 8

Хотя PHP может предоставлять множество динамических функций для разных типов данных, эти операции не волшебны, и данные по-прежнему сохраняются в качестве основных типов данных внутри того, что называется zval, что является технически сложной хэш-таблицей внутри родной zend api. Как и любой другой тип данных на любом языке, каждый zval будет существовать только в течение конечного периода. Для PHP этот период (максимально) - период обработки HTTP-запроса. В любой ситуации, чтобы сделать эти данные длиннее, чем один запрос, он должен быть преобразован из исходного zval в какой-либо другой вид, а затем каким-то образом сохранен (сюда относятся сложные типы, такие как объекты PHP, а также базовые типы, такие как Интс). Это всегда требует повторной инициализации каждого zval, а затем преобразования данных обратно из хранимой формы обратно в различные типы данных PHP в zval. Некоторые форматы хранения, такие как BSON, будут быстрее, чем сериализованные строки PHP, но (по крайней мере, на данный момент) это не обеспечит значительную часть заметного скачка производительности, поскольку он нигде не близок к производительности сохранения исходного zval по нескольким запросам. Вам все равно придется сериализовать эти данные в некотором роде, пройти время хранения, затем извлечь его и затем неэтериализировать. В настоящее время нет реальных решений для этого.

Обратите внимание, что PHP может иметь три разных области: SAPI, который инициирует и, в конечном счете, обрабатывает все состояния в каждом запросе; расширения, которые инициируются до начала каждого события запроса; и затем область script, которая инициируется каждым запросом. Все PHP-классы инициируются в области script, но могут быть доступны как для расширений, так и для SAPI. Но единственным областью, которая может существовать за каждым отдельным запросом, является SAPI. Другими словами, объект PHP может поддерживаться только в нескольких запросах внутри SAPI (расширение не может помочь в этой проблеме в настоящее время), поэтому только пользовательский SAPI может поддерживать zvals в запросах.

Ответ 9

Вы можете переписать свое приложение на ReactPHP, что создаст веб-сервер в одном длительном PHP-процессе (как и Node.js или Web.py). Затем вы можете создать свой большой объект один раз (при запуске сервера) в качестве глобальной переменной и получить доступ к нему из обработчиков событий запроса.