Предпочтительный метод хранения массивов PHP: json_encode или serialize?
Я нуждаюсь в сохранении многомерного ассоциативного массива данных в текстовом файле для кэширования. Периодически мне может понадобиться конвертировать его в JSON для использования в веб-приложении, но подавляющее большинство времени я буду использовать массив непосредственно в PHP.
Будет ли более эффективно сохранять массив в формате JSON или как сериализованный массив PHP в этом текстовом файле? Я искал информацию и заметил, что в последних версиях PHP (5.3) функция json_decode
на самом деле быстрее, чем unserialize
.
В настоящее время я склоняюсь к тому, чтобы хранить массив в формате JSON, так как мне кажется, что его проще читать человеку в случае необходимости, он может использоваться как в PHP, так и в JavaScript с минимальными усилиями, и, судя по прочитанному, его может быть даже быстрее декодировать (не совсем уверен насчёт кодирования, правда).
Есть ли у кого-то опыт, связанный с подводными камнями этого метода? Кто-то может привести хорошие бенчмарки, показывающие преимущества производительности одного из методов?
5 ответ(ов)
Вы также можете заинтересоваться проектом igbinary на GitHub, который предоставляет альтернативный механизм сериализации для PHP.
Мои произвольные показатели производительности, с использованием PHP 5.3.5 на 64-битной платформе, показывают следующие результаты:
JSON:
- Кодирование JSON заняло 2.180496931076 секунд
- Декодирование JSON заняло 9.8368630409241 секунд
- Размер сериализованной строки: 13993
Нативный PHP:
- Сериализация PHP заняла 2.9125759601593 секунд
- Десериализация PHP заняла 6.4348418712616 секунд
- Размер сериализованной строки: 20769
Igbinary:
- ПОЛУЧЕНО: Сериализация igbinary заняла 1.6099879741669 секунд
- ПОЛУЧЕНО: Десериализация igbinary заняла 4.7737920284271 секунд
- ПОЛУЧЕНО: Размер сериализованной строки: 4467
Как видите, функция igbinary_serialize()
и igbinary_unserialize()
работают быстрее и требуют меньше дискового пространства.
Я использовал код fillArray(0, 3)
, как было указано выше, но сделал ключи массива более длинными строками.
Igbinary может хранить те же типы данных, что и встроенная сериализация PHP (так что с объектами и т.д. проблем не возникнет), и вы можете указать PHP 5.3 использовать его для работы с сессиями, если это вам необходимо.
Также см. данный документ — в частности, слайды 14/15/16.
На основании проведенного тестирования можно сделать следующие выводы о производительности JSON и сериализации в PHP:
JSON кодируется быстрее, чем сериализованные данные. Время выполнения json_encode() составило примерно 0.067 секунд, тогда как serialize() заняла около 0.121 секунд. Это означает, что json_encode() примерно на 80.52% быстрее.
При декодировании данных json_decode() работает медленнее, чем unserialize(). Время выполнения json_decode() составило около 0.225 секунд, в то время как unserialize() заняла около 0.212 секунд. Это делает unserialize() на 6.02% быстрее по сравнению с json_decode().
Размер закодированной строки JSON составляет 1,277,772 байт, в то время как сериализованная строка занимает 1,955,548 байт. Таким образом, строка JSON оказывается примерно на 53.04% меньше по размеру.
В итоге, можно заключить, что для кодирования данных лучше использовать JSON, так как он быстрее и создает меньшую строку. Однако для декодирования сериализованные данные обрабатываются немного быстрее.
Я провел тест, который включает производительность сериализации и десериализации. Вот результаты, которые я получил:
Сериализация
JSON закодирован за 2.5738489627838 секунды
PHP сериализация заняла 5.2861361503601 секунды
Сериализация: json_encode() был примерно на 105.38% быстрее, чем serialize()
Десериализация
JSON декодирован за 10.915472984314 секунды
PHP десериализация заняла 7.6223039627075 секунды
Десериализация: unserialize() был примерно на 43.20% быстрее, чем json_decode()
Таким образом, JSON кажется быстрее при кодировании, но медленнее при декодировании. Это может зависеть от вашего приложения и того, что вы планируете делать чаще.
Вы правы, что на StackOverflow могут быть ответы, которые устарели. Я провел собственное тестирование в PHP 7.4 и хотел бы поделиться результатами, которые могут оказаться полезными.
В ходе тестов я сравнил скорость и использование памяти для сериализации, десериализации, а также для записи и чтения из файла. В общем, результаты показали, что serialize
/unserialize
значительно быстрее и менее затратен по памяти по сравнению с json_encode
/json_decode
.
Вот основные результаты:
Длина данных:
- Var Export: 11447 байт
- Serialized: 11541 байт
- JSON Encoded: 11895 байт
- Размер файла после file_put_contents: 11464 байт
Время выполнения (в секундах):
- JSON Encode: 1.92
- Serialize: 0.16
- File Put Contents (FPC): 6.28
- JSON Decode: 1.75
- Unserialize: 0.19
- Var Export and Include: 3.20
Использование памяти (в байтах):
- JSON Encode Memory: 12288
- Serialize Memory: 12288
- FPC Memory: 0
- JSON Decoded Memory: 16384
- Unserialize Memory: 14360
- Var Export and Include Memory: 192
Если подводить итог, serialize
/unserialize
действительно показывают лучшие результаты по времени и памяти в PHP 7.4 по сравнению с JSON. Эти данные также предполагают, что file_put_contents
является менее эффективным по времени, но не потребляет памяти (что соответствует процессу записи в файл).
Надеюсь, эти результаты помогут вам в вашей работе, и вы сможете принять более обоснованные решения, основываясь на них. Если у вас есть дополнительные вопросы или требуется разбор конкретных моментов, не стесняйтесь задавать!
Похоже, что я собираюсь использовать сериализацию по двум причинам:
- Кто-то отметил, что
unserialize
быстрее, чемjson_decode
, и использование в сценарии чтения кажется более вероятным, чем в сценарии записи. - У меня были проблемы с
json_encode
, когда в данных были строки с некорректными символами UTF-8. В таких случаях строка получается пустой, что приводит к потере информации.
Как сделать класс сериализуемым в JSON
Возвращение JSON из PHP-скрипта
Ошибка "Невозможно использовать объект типа stdClass как массив"
Можно ли привязать массив к условию IN() в запросе PDO?
Как добавить элементы в пустой массив в PHP?