Предпочтительный способ хранения массивов PHP (json_encode vs serialize)

608

Мне нужно хранить многомерный ассоциативный массив данных в плоский файл для целей кэширования. Иногда я могу столкнуться с необходимостью конвертировать его в JSON для использования в моем веб-приложении, но в большинстве случаев я буду использовать массив непосредственно в PHP.

Будет ли эффективнее хранить этот массив в виде JSON или сериализованного массива PHP в этом текстовом файле? Я посмотрел вокруг, и кажется, что в новейших версиях PHP (5.3), json_decodeна самом деле быстрее, чем unserialize.

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

Кто-нибудь знает какие-либо подводные камни? У кого-нибудь есть хорошие тесты, чтобы показать преимущества производительности любого метода?

KyleFarris
источник

Ответы:

563

Зависит от ваших приоритетов.

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

  • В отличие от serialize()вас необходимо добавить дополнительный параметр, чтобы сохранить символы UTF-8 нетронутыми: json_encode($array, JSON_UNESCAPED_UNICODE) (в противном случае он преобразует символы UTF-8 в escape-последовательности Unicode).
  • JSON не будет иметь памяти о том, каким был исходный класс объекта (они всегда восстанавливаются как экземпляры stdClass).
  • Вы не можете использовать __sleep()и __wakeup()с JSON
  • По умолчанию только открытые свойства сериализуются с помощью JSON. ( PHP>=5.4вы можете реализовать JsonSerializable, чтобы изменить это поведение).
  • JSON более переносим

И есть, вероятно, несколько других отличий, о которых я не могу думать в данный момент.

Простой тест скорости, чтобы сравнить два

<?php

ini_set('display_errors', 1);
error_reporting(E_ALL);

// Make a big, honkin test array
// You may need to adjust this depth to avoid memory limit errors
$testArray = fillArray(0, 5);

// Time json encoding
$start = microtime(true);
json_encode($testArray);
$jsonTime = microtime(true) - $start;
echo "JSON encoded in $jsonTime seconds\n";

// Time serialization
$start = microtime(true);
serialize($testArray);
$serializeTime = microtime(true) - $start;
echo "PHP serialized in $serializeTime seconds\n";

// Compare them
if ($jsonTime < $serializeTime) {
    printf("json_encode() was roughly %01.2f%% faster than serialize()\n", ($serializeTime / $jsonTime - 1) * 100);
}
else if ($serializeTime < $jsonTime ) {
    printf("serialize() was roughly %01.2f%% faster than json_encode()\n", ($jsonTime / $serializeTime - 1) * 100);
} else {
    echo "Impossible!\n";
}

function fillArray( $depth, $max ) {
    static $seed;
    if (is_null($seed)) {
        $seed = array('a', 2, 'c', 4, 'e', 6, 'g', 8, 'i', 10);
    }
    if ($depth < $max) {
        $node = array();
        foreach ($seed as $key) {
            $node[$key] = fillArray($depth + 1, $max);
        }
        return $node;
    }
    return 'empty';
}
Питер Бейли
источник
31
«JSON преобразует символы UTF-8 в escape-последовательности Юникода». Больше не обязательно верно: у нас теперь есть JSON_UNESCAPED_UNICODE.
TRiG
32
Здесь мы почти 5 лет спустя, и я снова запустил тесты (только json_encode), и в среднем это примерно на 131% быстрее, чем сейчас. Таким образом, в 5.4.x должно быть несколько хороших улучшений этой функции по сравнению с 5.3.x. В частности, я использую 5.4.24 на CentOS 6. Итак, ура для JSON!
KyleFarris
8
в моем случае мы кодируем один раз и много декодируем, поэтому мы провели сравнительный анализ json_decode и unserialize, и результаты были закодированы в JSON за 0,06662392616272 секунд. PHP не десериализован за 0,093269109725952 секунд. json_decode () оказался примерно на 39,99% быстрее, чем unserialize ()
AMB
21
Интересно: если вы запустите этот код на 3v4l.org , последние версии разработки PHP7 будут запускать сериализацию быстрее, чем json_encode: «serialize () был примерно на 76,53% быстрее, чем json_encode ()»
marcvangend
21
2017, PHP 7.1 иserialize() was roughly 35.04% faster than json_encode()
Элиас Соарес
239

JSON проще и быстрее, чем формат сериализации PHP, и его следует использовать, если :

  • Вы храните глубоко вложенные массивы: json_decode()«Эта функция вернет false, если данные в кодировке JSON глубже 127 элементов».
  • Вы храните объекты, которые должны быть не сериализованы, как правильный класс.
  • Вы взаимодействуете со старыми версиями PHP, которые не поддерживают json_decode
Greg
источник
12
Отличный ответ. Ха-ха, 127 уровней глубоко, кажется немного безумным; К счастью, я собираюсь только как 2-3 максимум. У вас есть какие-либо данные, подтверждающие тот факт, что json_decode / json_encode работает быстрее, чем десериализация / сериализация?
KyleFarris
1
Я проверил это некоторое время назад, и json вышел быстрее - у меня больше нет данных.
Грег
47
«5.3.0 Добавлена ​​необязательная глубина. Глубина рекурсии по умолчанию была увеличена со 128 до 512»
giorgio79
4
Я хотел бы добавить еще один элемент в приведенный выше список: json_encode () не должен использоваться, если ваши данные могут содержать недопустимые последовательности байтов UTF-8. Он просто возвращает false для таких данных. Попробуйте, например: var_dump (json_encode ("\ xEF \ xEF"));
Пако
2
Это не правда, что это быстрее в целом. Если у вас небольшой массив с ~ 500 записями, то десериализация / сериализация на самом деле на 200-400% быстрее, чем json_decode / json_encode (PHP 5.6.19)
Адам,
59

Я написал статью на эту тему: « Кэшировать большой массив: JSON, serialize или var_export? » . В этом посте показано, что сериализация - лучший выбор для маленьких и больших массивов. Для очень больших массивов (> 70 МБ) JSON - лучший выбор.

Taco
источник
8
Ссылка больше не доступна.
Мартин Тома
1
Спасибо, лось, я обновил ссылку. Хотя этой статье уже почти 6 лет, и она может быть не такой точной для текущих версий PHP.
Тако
Я сделал несколько тестов и сделал простую функцию для тестирования, с большими массивами (для них использовалась функция Питера Бэйли), что json_encode()примерно на 80-150% быстрее (это действительно идет вверх и вниз), чем serialize(), примерно с 300 итерациями. Но при использовании меньших массивов ( array("teams" => array(1 => array(4 arrays of players), 2 => array(4 arrays of players)))) я провел тестирование с 750 000 итераций, и в этом случае serialize()это примерно на 6-10% быстрее. Моя функция берет среднее время для всех итераций и сравнивает их. Я мог бы опубликовать это здесь как один из ответов
MiChAeLoKGB
если данные используются только PHP, var_export - моя вещь. Просто нужно быть осторожным с возможными синтаксическими ошибками во включенной мысли.
Gfra54
3
блог больше не существует
popeye
53

Вы также можете быть заинтересованы в https://github.com/phadej/igbinary - который предоставляет другой «механизм» сериализации для PHP.

Мои случайные / произвольные показатели «производительности» с использованием PHP 5.3.5 на 64-битной платформе показывают:

JSON:

  • JSON закодирован за 2,180496931076 секунд
  • JSON расшифровывается за 9,8368630409241 секунд
  • Серийный размер "String": 13993

Родной PHP:

  • PHP сериализован за 2,9125759601593 секунд
  • PHP не сериализован за 6,4348418712616 секунд
  • Сериализованный "String" размер: 20769

Игбинар:

  • WIN igbinary сериализован за 1.6099879741669 секунд
  • WIN igbinrary десериализуются в 4.7737920284271 секунд
  • WIN сериализованный "String" Размер: 4467

Таким образом, igbinary_serialize () и igbinary_unserialize () быстрее и занимают меньше места на диске.

Я использовал код fillArray (0, 3), как указано выше, но сделал ключи массива более длинными.

igbinary может хранить те же типы данных, что и собственная сериализация PHP (поэтому нет проблем с объектами и т. д.), и вы можете указать PHP5.3 использовать его для обработки сеансов, если вы того пожелаете.

Смотрите также http://ilia.ws/files/zendcon_2010_hidden_features.pdf - конкретные слайды 14/15/16

Дэвид Гудвин
источник
25

Y только что протестировал сериализованный код, а json кодирует и декодирует, плюс размер, который он будет хранить в сохраненной строке.

JSON encoded in 0.067085981369 seconds. Size (1277772)
PHP serialized in 0.12110209465 seconds. Size (1955548)
JSON decode in 0.22470498085 seconds
PHP serialized in 0.211947917938 seconds
json_encode() was roughly 80.52% faster than serialize()
unserialize() was roughly 6.02% faster than json_decode()
JSON string was roughly 53.04% smaller than Serialized string

Мы можем заключить, что JSON кодирует быстрее и приводит к меньшей строке, но unserialize быстрее декодирует строку.

Blunk
источник
6
Я не знаю, почему люди всегда делают тест производительности с таким маленьким набором данных. При этом у вас есть все накладные расходы, которые добавляют ошибки к вашим результатам. И если люди заинтересованы в производительности, это, вероятно, потому, что у них очень большой набор данных, потому что нет смысла набирать микросекунду один раз.
Ян Сэгон
1
Довольно часто я перебираю множество небольших наборов данных. С сотнями небольших наборов данных получение 1 мс для каждого все еще интересно.
Teson
@YannSagon Даже с небольшими наборами данных имеет смысл провести тест производительности. Как вы должны знать перед тестом, если это всего лишь около одного микросекунды?
Адам
17

Если вы кэшируете информацию, которую в конечном итоге захотите «включить» на более позднем этапе, вы можете попробовать использовать var_export . Таким образом, вы получаете удар только в «сериализации», а не в «сериализации».

Джордан С. Джонс
источник
Скорее всего, это самый быстрый способ. Я написал пример для SO «PHP - быстрая сериализация / десериализация»: stackoverflow.com/questions/2545455/…
dave1010
12

Я добавил тест, чтобы включить производительность десериализации. Вот цифры, которые я получил.

Serialize

JSON encoded in 2.5738489627838 seconds
PHP serialized in 5.2861361503601 seconds
Serialize: json_encode() was roughly 105.38% faster than serialize()


Unserialize

JSON decode in 10.915472984314 seconds
PHP unserialized in 7.6223039627075 seconds
Unserialize: unserialize() was roughly 43.20% faster than json_decode() 

Таким образом, json, кажется, быстрее для кодирования, но медленнее в декодировании. Так что это может зависеть от вашего приложения и того, что вы ожидаете сделать больше всего.

Джефф Уайтинг
источник
9

Действительно хорошая тема и после прочтения нескольких ответов, я хочу поделиться своими экспериментами на эту тему.

У меня есть сценарий использования, когда к какой-то «огромной» таблице нужно обращаться почти каждый раз, когда я общаюсь с базой данных (не спрашиваю почему, просто факт). Система кэширования базы данных не подходит, так как она не будет кэшировать различные запросы, поэтому я думаю о системах кэширования php.

Я пытался, apcuно это не соответствовало потребностям, в этом случае память недостаточно надежна. Следующим шагом было кеширование в файл с сериализацией.

В таблице 14355 записей с 18 столбцами, это мои тесты и статистика чтения сериализованного кэша:

JSON:

Как вы все сказали, основное неудобство с json_encode/ json_decodeзаключается в том, что он преобразует все в StdClassэкземпляр (или объект). Если вам нужно зациклить его, вы, вероятно, будете преобразовывать его в массив, и да, это увеличивает время преобразования

среднее время: 780,2 мс; использование памяти: 41,5 МБ; размер файла кэша: 3.8MB

Msgpack

@hutch упоминает msgpack . Симпатичный сайт. Давайте попробуем?

среднее время: 497 мс; использование памяти: 32 МБ; Размер файла кэша: 2,8 МБ

Это лучше, но требует нового расширения; компиляция иногда боится людей ...

IgBinary

@GingerDog упоминает igbinary . Обратите внимание, что я установил, igbinary.compact_strings=Offпотому что меня больше интересует производительность чтения, чем размер файла.

среднее время: 411,4 мс; использование памяти: 36,75 МБ; Размер файла кэша: 3,3 МБ

Лучше, чем MSG Pack. Тем не менее, этот тоже требует компиляции.

serialize/unserialize

среднее время: 477,2 мс; использование памяти: 36,25 МБ; размер файла кэша: 5,9 МБ

Чем лучше производительность, чем JSON, тем больше массив, тем медленнее json_decode, но вы уже новичок в этом.

Эти внешние расширения сужают размер файла и кажутся великолепными на бумаге. Числа не лгут *. Какой смысл компилировать расширение, если вы получаете почти те же результаты, что и при использовании стандартной функции PHP?

Мы также можем сделать вывод, что в зависимости от ваших потребностей вы выберете что-то другое, чем кто-либо другой:

  • IgBinary действительно хорош и работает лучше, чем MsgPack
  • Msgpack лучше сжимает ваши данные (обратите внимание, что я не пробовал опцию igbinary compact.string).
  • Не хотите компилировать? Используйте стандарты.

Вот и все, еще одно сравнение методов сериализации, чтобы помочь вам выбрать один!

* Протестировано с PHPUnit 3.7.31, php 5.5.10 - только декодирование со стандартным жестким диском и старым двухъядерным процессором - средние числа в 10 тестах с одинаковыми вариантами использования, ваша статистика может отличаться

soyuka
источник
Почему бы не передать флаг json_decode для принудительного возвращения массивов?
Алексей Ярошевич
Потому что это медленно. Я не проверял это, но я думаю, что просто заставить изменение типа с php быстрее.
союка
Я просто знаю, что создание массивов намного быстрее, чем объектов в php.
Алексей Ярошевич
Итак, вы говорите о том json_decode($object, true), что в основном это будет происходить так же, как и (array) json_decode($object)рекурсивно, так что это будет одинаковым поведением, и это будет иметь значительные затраты в обоих случаях. Обратите внимание , что я не тестировал производительность между посмотреть различие StdClassи , arrayно это не совсем точек здесь.
союка
Я уверен, что это еще одна цена, потому что это делается на более низком уровне без объектов.
Алексей Ярошевич
8

Похоже, я буду использовать serialize по двум причинам:

  • Кто-то указал, что unserialize быстрее, чем json_decode, и случай «чтения» звучит более вероятно, чем случай «записи».

  • У меня были проблемы с json_encode при наличии строк с недопустимыми символами UTF-8. Когда это происходит, строка оказывается пустой, что приводит к потере информации.

urraka
источник
Не могли бы вы уточнить ваш последний пункт с примером
Навин Сарое
6

Я очень тщательно протестировал это на довольно сложном, слегка вложенном мультихэше со всеми видами данных (строка, NULL, целые числа), и сериализация / десериализация закончилась намного быстрее, чем json_encode / json_decode.

Единственное преимущество, которое json имеет в моих тестах, это меньший «упакованный» размер.

Это сделано в PHP 5.3.3, дайте мне знать, если вы хотите больше деталей.

Вот результаты тестов, а затем код для их создания. Я не могу предоставить тестовые данные, так как они раскрывают информацию, которую я не могу выпустить в дикую природу.

JSON encoded in 2.23700618744 seconds
PHP serialized in 1.3434419632 seconds
JSON decoded in 4.0405561924 seconds
PHP unserialized in 1.39393305779 seconds

serialized size : 14549
json_encode size : 11520
serialize() was roughly 66.51% faster than json_encode()
unserialize() was roughly 189.87% faster than json_decode()
json_encode() string was roughly 26.29% smaller than serialize()

//  Time json encoding
$start = microtime( true );
for($i = 0; $i < 10000; $i++) {
    json_encode( $test );
}
$jsonTime = microtime( true ) - $start;
echo "JSON encoded in $jsonTime seconds<br>";

//  Time serialization
$start = microtime( true );
for($i = 0; $i < 10000; $i++) {
    serialize( $test );
}
$serializeTime = microtime( true ) - $start;
echo "PHP serialized in $serializeTime seconds<br>";

//  Time json decoding
$test2 = json_encode( $test );
$start = microtime( true );
for($i = 0; $i < 10000; $i++) {
    json_decode( $test2 );
}
$jsonDecodeTime = microtime( true ) - $start;
echo "JSON decoded in $jsonDecodeTime seconds<br>";

//  Time deserialization
$test2 = serialize( $test );
$start = microtime( true );
for($i = 0; $i < 10000; $i++) {
    unserialize( $test2 );
}
$unserializeTime = microtime( true ) - $start;
echo "PHP unserialized in $unserializeTime seconds<br>";

$jsonSize = strlen(json_encode( $test ));
$phpSize = strlen(serialize( $test ));

echo "<p>serialized size : " . strlen(serialize( $test )) . "<br>";
echo "json_encode size : " . strlen(json_encode( $test )) . "<br></p>";

//  Compare them
if ( $jsonTime < $serializeTime )
{
    echo "json_encode() was roughly " . number_format( ($serializeTime / $jsonTime - 1 ) * 100, 2 ) . "% faster than serialize()";
}
else if ( $serializeTime < $jsonTime )
{
    echo "serialize() was roughly " . number_format( ($jsonTime / $serializeTime - 1 ) * 100, 2 ) . "% faster than json_encode()";
} else {
    echo 'Unpossible!';
}
    echo '<BR>';

//  Compare them
if ( $jsonDecodeTime < $unserializeTime )
{
    echo "json_decode() was roughly " . number_format( ($unserializeTime / $jsonDecodeTime - 1 ) * 100, 2 ) . "% faster than unserialize()";
}
else if ( $unserializeTime < $jsonDecodeTime )
{
    echo "unserialize() was roughly " . number_format( ($jsonDecodeTime / $unserializeTime - 1 ) * 100, 2 ) . "% faster than json_decode()";
} else {
    echo 'Unpossible!';
}
    echo '<BR>';
//  Compare them
if ( $jsonSize < $phpSize )
{
    echo "json_encode() string was roughly " . number_format( ($phpSize / $jsonSize - 1 ) * 100, 2 ) . "% smaller than serialize()";
}
else if ( $phpSize < $jsonSize )
{
    echo "serialize() string was roughly " . number_format( ($jsonSize / $phpSize - 1 ) * 100, 2 ) . "% smaller than json_encode()";
} else {
    echo 'Unpossible!';
}
Мистер Сокс
источник
Я только что провел аналогичный тест с PHP 5.4.12 и нашел похожие результаты: {un,} сериализация происходит быстрее. Мои данные вложены в 3 уровня (900k сериализовано).
Сорпигал
6

Я также сделал небольшой тест. Мои результаты были одинаковыми. Но мне нужно производительность декодирования. То, что я заметил, как сказали несколько человек выше, unserializeбыстрее, чем json_decode. unserializeзанимает примерно 60-70% json_decodeвремени. Итак, вывод довольно прост: когда вам нужна производительность при кодировании, используйте json_encode, когда вам нужна производительность при декодировании, используйте unserialize. Поскольку вы не можете объединить две функции, вы должны сделать выбор, где вам нужно больше производительности.

Мой тест в псевдо:

  • Определите массив $ arr с несколькими случайными ключами и значениями
  • для х <100; х ++; сериализовать и json_encode массива и $ arr
  • для у <1000; у ++; json_decode строка в кодировке json - время расчета
  • для у <1000; у ++; десериализовать сериализованную строку - время расчета
  • повторить результат, который был быстрее

На avarage: unserialize выиграл 96 раз по сравнению с json_decode. С средним значением 1,5 мс над 2,5 мс.

Jelmer
источник
3

Прежде чем принять окончательное решение, имейте в виду, что формат JSON небезопасен для ассоциативных массивов - json_decode()вместо этого он будет возвращать их в виде объектов:

$config = array(
    'Frodo'   => 'hobbit',
    'Gimli'   => 'dwarf',
    'Gandalf' => 'wizard',
    );
print_r($config);
print_r(json_decode(json_encode($config)));

Выход:

Array
(
    [Frodo] => hobbit
    [Gimli] => dwarf
    [Gandalf] => wizard
)
stdClass Object
(
    [Frodo] => hobbit
    [Gimli] => dwarf
    [Gandalf] => wizard
)
слишком много PHP
источник
Действительно, ты прав. Я имею в виду, что это Java - объект нотации Afterall! К счастью, если вы знаете, что то, что вы кодировали, используя json_encodeассоциативный массив, вы можете легко принудительно вернуть его обратно в массив следующим образом: $json = json_encode($some_assoc_array); $back_to_array = (array)json_decode($json);также хорошо отметить, что вы можете обращаться к объектам так же, как к массивам в PHP, так и в типичном сценарии, никто бы даже не знал разницу. Хороший момент, хотя!
KyleFarris
30
@toomuchphp, извините, но вы не правы. Существует второй параметр для json_decode 'bool $ assoc = false', который заставляет json_decode создавать массив. @KyleFarris, это также должно быть быстрее, чем использование Typecast для массива.
Январь
ответ не правильный. при использовании true в качестве второго параметра функции json_decode () будет возвращать ассоциативные массивы вместо объектов.
Марвин Салдингер
3

Во-первых, я изменил сценарий, чтобы сделать еще несколько тестов (а также выполнить 1000 прогонов вместо 1):

<?php

ini_set('display_errors', 1);
error_reporting(E_ALL);

// Make a big, honkin test array
// You may need to adjust this depth to avoid memory limit errors
$testArray = fillArray(0, 5);

$totalJsonTime = 0;
$totalSerializeTime = 0;
$totalJsonWins = 0;

for ($i = 0; $i < 1000; $i++) {
    // Time json encoding
    $start = microtime(true);
    $json = json_encode($testArray);
    $jsonTime = microtime(true) - $start;
    $totalJsonTime += $jsonTime;

    // Time serialization
    $start = microtime(true);
    $serial = serialize($testArray);
    $serializeTime = microtime(true) - $start;
    $totalSerializeTime += $serializeTime;

    if ($jsonTime < $serializeTime) {
        $totalJsonWins++;
    }
}

$totalSerializeWins = 1000 - $totalJsonWins;

// Compare them
if ($totalJsonTime < $totalSerializeTime) {
    printf("json_encode() (wins: $totalJsonWins) was roughly %01.2f%% faster than serialize()\n", ($totalSerializeTime / $totalJsonTime - 1) * 100);
} else {
    printf("serialize() (wins: $totalSerializeWins) was roughly %01.2f%% faster than json_encode()\n", ($totalJsonTime / $totalSerializeTime - 1) * 100);
}

$totalJsonTime = 0;
$totalJson2Time = 0;
$totalSerializeTime = 0;
$totalJsonWins = 0;

for ($i = 0; $i < 1000; $i++) {
    // Time json decoding
    $start = microtime(true);
    $orig = json_decode($json, true);
    $jsonTime = microtime(true) - $start;
    $totalJsonTime += $jsonTime;

    $start = microtime(true);
    $origObj = json_decode($json);
    $jsonTime2 = microtime(true) - $start;
    $totalJson2Time += $jsonTime2;

    // Time serialization
    $start = microtime(true);
    $unserial = unserialize($serial);
    $serializeTime = microtime(true) - $start;
    $totalSerializeTime += $serializeTime;

    if ($jsonTime < $serializeTime) {
        $totalJsonWins++;
    }
}

$totalSerializeWins = 1000 - $totalJsonWins;


// Compare them
if ($totalJsonTime < $totalSerializeTime) {
    printf("json_decode() was roughly %01.2f%% faster than unserialize()\n", ($totalSerializeTime / $totalJsonTime - 1) * 100);
} else {
    printf("unserialize() (wins: $totalSerializeWins) was roughly %01.2f%% faster than json_decode()\n", ($totalJsonTime / $totalSerializeTime - 1) * 100);
}

// Compare them
if ($totalJson2Time < $totalSerializeTime) {
    printf("json_decode() was roughly %01.2f%% faster than unserialize()\n", ($totalSerializeTime / $totalJson2Time - 1) * 100);
} else {
    printf("unserialize() (wins: $totalSerializeWins) was roughly %01.2f%% faster than array json_decode()\n", ($totalJson2Time / $totalSerializeTime - 1) * 100);
}

function fillArray( $depth, $max ) {
    static $seed;
    if (is_null($seed)) {
        $seed = array('a', 2, 'c', 4, 'e', 6, 'g', 8, 'i', 10);
    }
    if ($depth < $max) {
        $node = array();
        foreach ($seed as $key) {
            $node[$key] = fillArray($depth + 1, $max);
        }
        return $node;
    }
    return 'empty';
}

Я использовал эту сборку PHP 7:

PHP 7.0.14 (cli) (сборка: 18 января 2017 г. 19:13:23) (NTS) Copyright (c) 1997-2016 PHP Group Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies с Zend OPcache v7.0.14, Copyright (c) 1999-2016, Zend Technologies

И мои результаты были:

serialize () (wins: 999) была примерно на 10,98% быстрее, чем json_encode (). unserialize () (wins: 987) была примерно на 33,26% быстрее, чем json_decode (). ()

Так ясно , сериализации / десериализации является самым быстрым способом, в то время как json_encode / декодирования является самым портативным.

Если вы рассматриваете сценарий, в котором вы читаете / записываете сериализованные данные в 10 раз или чаще, чем вам нужно отправлять или получать из системы, отличной от PHP, вам все равно лучше использовать сериализацию / десериализацию и иметь json_encode или json_decode до сериализации с точки зрения времени.

Шон Толидано
источник
2

Проверьте результаты здесь (извините за взлом, поместив код PHP в поле кода JS):

http://jsfiddle.net/newms87/h3b0a0ha/embedded/result/

РЕЗУЛЬТАТЫ: serialize()и unserialize()оба они значительно быстрее в PHP 5.4 на массивах различного размера.

Я сделал тестовый скрипт на реальных данных для сравнения json_encode и serialize и json_decode и unserialize. Тест проводился на системе кеширования на сайте электронной коммерции. Он просто берет данные, уже находящиеся в кеше, и проверяет время кодирования / декодирования (или сериализации / десериализации) всех данных, и я помещаю их в легко видимую таблицу.

Я запустил это на сервере общего хостинга PHP 5.4.

Результаты были очень убедительными, что для этих больших и малых наборов данных сериализация и десериализация были явными победителями. В частности, для моего случая использования json_decode и unserialize являются наиболее важными для системы кэширования. Unserialize был почти повсеместным победителем здесь. Обычно это было в 2-4 раза (иногда в 6 или 7 раз) быстрее, чем json_decode.

Интересно отметить разницу в результатах от @ peter-bailey.

Вот код PHP, используемый для генерации результатов:

<?php

ini_set('display_errors', 1);
error_reporting(E_ALL);

function _count_depth($array)
{
    $count     = 0;
    $max_depth = 0;
    foreach ($array as $a) {
        if (is_array($a)) {
            list($cnt, $depth) = _count_depth($a);
            $count += $cnt;
            $max_depth = max($max_depth, $depth);
        } else {
            $count++;
        }
    }

    return array(
        $count,
        $max_depth + 1,
    );
}

function run_test($file)
{
    $memory     = memory_get_usage();
    $test_array = unserialize(file_get_contents($file));
    $memory     = round((memory_get_usage() - $memory) / 1024, 2);

    if (empty($test_array) || !is_array($test_array)) {
        return;
    }

    list($count, $depth) = _count_depth($test_array);

    //JSON encode test
    $start            = microtime(true);
    $json_encoded     = json_encode($test_array);
    $json_encode_time = microtime(true) - $start;

    //JSON decode test
    $start = microtime(true);
    json_decode($json_encoded);
    $json_decode_time = microtime(true) - $start;

    //serialize test
    $start          = microtime(true);
    $serialized     = serialize($test_array);
    $serialize_time = microtime(true) - $start;

    //unserialize test
    $start = microtime(true);
    unserialize($serialized);
    $unserialize_time = microtime(true) - $start;

    return array(
        'Name'                   => basename($file),
        'json_encode() Time (s)' => $json_encode_time,
        'json_decode() Time (s)' => $json_decode_time,
        'serialize() Time (s)'   => $serialize_time,
        'unserialize() Time (s)' => $unserialize_time,
        'Elements'               => $count,
        'Memory (KB)'            => $memory,
        'Max Depth'              => $depth,
        'json_encode() Win'      => ($json_encode_time > 0 && $json_encode_time < $serialize_time) ? number_format(($serialize_time / $json_encode_time - 1) * 100, 2) : '',
        'serialize() Win'        => ($serialize_time > 0 && $serialize_time < $json_encode_time) ? number_format(($json_encode_time / $serialize_time - 1) * 100, 2) : '',
        'json_decode() Win'      => ($json_decode_time > 0 && $json_decode_time < $serialize_time) ? number_format(($serialize_time / $json_decode_time - 1) * 100, 2) : '',
        'unserialize() Win'      => ($unserialize_time > 0 && $unserialize_time < $json_decode_time) ? number_format(($json_decode_time / $unserialize_time - 1) * 100, 2) : '',
    );
}

$files = glob(dirname(__FILE__) . '/system/cache/*');

$data = array();

foreach ($files as $file) {
    if (is_file($file)) {
        $result = run_test($file);

        if ($result) {
            $data[] = $result;
        }
    }
}

uasort($data, function ($a, $b) {
    return $a['Memory (KB)'] < $b['Memory (KB)'];
});

$fields = array_keys($data[0]);
?>

<table>
    <thead>
    <tr>
        <?php foreach ($fields as $f) { ?>
            <td style="text-align: center; border:1px solid black;padding: 4px 8px;font-weight:bold;font-size:1.1em"><?= $f; ?></td>
        <?php } ?>
    </tr>
    </thead>

    <tbody>
    <?php foreach ($data as $d) { ?>
        <tr>
            <?php foreach ($d as $key => $value) { ?>
                <?php $is_win = strpos($key, 'Win'); ?>
                <?php $color = ($is_win && $value) ? 'color: green;font-weight:bold;' : ''; ?>
                <td style="text-align: center; vertical-align: middle; padding: 3px 6px; border: 1px solid gray; <?= $color; ?>"><?= $value . (($is_win && $value) ? '%' : ''); ?></td>
            <?php } ?>
        </tr>
    <?php } ?>
    </tbody>
</table>
newms87
источник
1

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

закром
источник
2
если это просто к вашему сведению, то лучше оставить комментарий.
технофил
0

JSON лучше, если вы хотите сделать резервную копию данных и восстановить их на другом компьютере или через FTP.

Например, при использовании serialize, если вы храните данные на сервере Windows, загружаете их по FTP и восстанавливаете на Linux, они больше не могут работать из-за перекодировки charachter, потому что serialize хранит длину строк и в Unicode > UTF-8, транскодирующий некоторый 1-байтовый символ, может иметь длину 2 байта, что приводит к сбою алгоритма.

Informate.it
источник
0

THX - для этого кода теста:

Мои результаты для массива, который я использую для конфигурации, выглядят как пара: JSON, закодированный за 0,0031511783599854 секунды,
PHP, сериализованный за 0,0037961006164551 секунд,
json_encode()был примерно на 20,47% быстрее, чем serialize() JSON, закодированный за 0,0070841312408447 секунд,
PHP, сериализованный за 0,0035839080810547 секунд,
unserialize()был примерно на 97,66% быстрее, чемjson_encode()

Так что - проверьте это на своих данных.

mk182
источник
Вы имеете в виду, что json_decode () в "unserialize () был примерно на 97,66% быстрее, чем json_encode ()", да?
Meezaan-ud-Din
0

Если подытожить то, что люди здесь говорят, json_decode / encode кажется быстрее, чем serialize / unserialize, НО Если вы выполните var_dump, тип сериализованного объекта будет изменен. Если по какой-то причине вы хотите сохранить тип, переходите к serialize!

(попробуйте например stdClass vs array)

сериализации / десериализации:

Array cache:
array (size=2)
  'a' => string '1' (length=1)
  'b' => int 2
Object cache:
object(stdClass)[8]
  public 'field1' => int 123
This cache:
object(Controller\Test)[8]
  protected 'view' => 

JSON кодировать / декодировать

Array cache:
object(stdClass)[7]
  public 'a' => string '1' (length=1)
  public 'b' => int 2
Object cache:
object(stdClass)[8]
  public 'field1' => int 123
This cache:
object(stdClass)[8]

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

Дэвид Константин
источник
Просто примечание: в большинстве других ответов говорится, что сериализация / десериализация происходит быстрее.
Ecker00
-3

Я бы предложил вам использовать Super Cache, который является механизмом файлового кэша, который не будет использовать json_encodeили serialize. Он прост в использовании и действительно быстр по сравнению с другим механизмом PHP Cache.

https://packagist.org/packages/smart-php/super-cache

Пример:

<?php
require __DIR__.'/vendor/autoload.php';
use SuperCache\SuperCache as sCache;

//Saving cache value with a key
// sCache::cache('<key>')->set('<value>');
sCache::cache('myKey')->set('Key_value');

//Retrieving cache value with a key
echo sCache::cache('myKey')->get();
?>
shabeer
источник
-1. Хотя это может быть лучшим решением, ни одна из частей этого ответа на самом деле не отвечает на вопрос ОП. В будущем, возможно, попробуйте ответить на вопрос, но оставьте в нижней части предположение, что альтернативное решение может стоить изучения.
starbeamrainbowlabs