Кращий метод для зберігання масивів PHP (json_encode vs serialize)


609

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

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

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

Хтось знає про якісь підводні камені? Хтось має хороші орієнтири, щоб показати переваги продуктивності будь-якого методу?

Відповіді:


563

Залежить від ваших пріоритетів.

Якщо продуктивність - ваша абсолютна характеристика водіння, то будь-якими способами користуйтеся найшвидшим. Просто переконайтесь, що ви повністю розумієте відмінності, перш ніж робити вибір

  • На відміну від serialize()вас потрібно додати додатковий параметр, щоб символи UTF-8 не торкнулися: json_encode($array, JSON_UNESCAPED_UNICODE) (інакше він перетворює символи UTF-8 в послідовності втечі 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 у послідовність уникнення унікоду." Більше не обов’язково правда: у нас зараз 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 проти десеріалізациі і результатів був JSON dcoded в 0.06662392616272 секунд <br> PHP десеріалізуются в 0.093269109725952 секунд <br> json_decode () був приблизно 39,99% швидше , ніж десеріалізіруются ()
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()
Elias Soares

239

JSON простіший і швидший, ніж формат серіалізації PHP, і його слід використовувати, якщо :

  • Ви зберігаєте глибоко вкладені масиви: json_decode()"Ця функція поверне помилкову, якщо кодовані JSON дані глибші за 127 елементів."
  • Ви зберігаєте об'єкти, які потрібно несеріалізувати як правильний клас
  • Ви взаємодієте зі старими версіями PHP, які не підтримують json_decode

12
Чудова відповідь. Ха-ха, 127 рівнів глибоких здаються трохи божевільними; на щастя, я їду лише як мінімум 2-3. Чи є у вас якісь дані, щоб створити резервну копію факту, що json_decode / json_encode швидше, ніж несеріалізувати / серіалізувати?
KyleFarris

1
Я тестував це деякий час тому, і json вийшов швидше - у мене вже немає даних.
Грег

47
"5.3.0 Додана додаткова глибина. Глибина рекурсії за замовчуванням збільшена з 128 до 512"
giorgio79

4
Я б додав ще один елемент до вищенаведеного списку: json_encode () не слід використовувати, якщо ваші дані можуть містити недійсні послідовності байтів UTF-8. Він просто повертає помилки для таких даних. Спробуйте, наприклад: var_dump (json_encode ("\ xEF \ xEF"));
pako

1
Це неправда, що це швидше загалом. Якщо у вас невеликий масив з приблизно 500 записами, то безсеріалізація / серіалізація насправді на 200-400% швидша, ніж json_decode / json_encode (PHP 5.6.19)
Адам

59

Я написав повідомлення в блозі на цю тему: " Кешуйте великий масив: JSON, serialize або var_export? " . У цій публікації показано, що серіалізація - найкращий вибір для малих та великих розмірів. Для дуже великих масивів (> 70MB) кращий вибір JSON.


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 секунди
  • розмір серіалізованого "Рядок": 13993

Рідний PHP:

  • PHP серіалізується за 2.9125759601593 секунди
  • PHP несеріалізується за 6.4348418712616 секунд
  • розмір серіалізованого "Рядок": 20769

Igbinary:

  • WIN igbinary серіалізувався за 1.6099879741669 секунд
  • WIN igbinrary несеріалізований за 4.7737920284271 секунди
  • WIN серіалізований "Рядок" Розмір: 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 кодує швидше і приводить до меншої рядку, але несеріалізація швидше розшифрує рядок.


6
Я не знаю, чому люди завжди роблять тест на ефективність з таким невеликим набором даних. При цьому у вас є всі накладні витрати, які додають помилок до результатів. І якщо люди зацікавлені в продуктивності, це, мабуть, тому, що вони мають дуже великий набір даних, тому що немає сенсу один раз отримати мікросекцію.
Янн Сагон

1
Досить часто я повторюю багато невеликих наборів даних. Маючи сотні невеликих наборів даних, набирати 1mS для кожного все ще цікаво.
Тесон

@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,8 МБ

Msgpack

@hutch згадує msgpack . Гарний веб-сайт. Спробуємо, чи не так?

середній час: 497 мс; використання пам'яті: 32 Мб; розмір файлу кеша: 2,8 МБ

Це краще, але вимагає нового розширення; складання іноді бояться людей ...

IgBinary

@GingerDog згадує ігбінарне . Зауважте, що я встановив це, igbinary.compact_strings=Offтому що я більше дбаю про ефективність читання, ніж про розмір файлу.

середній час: 411,4 мс; використання пам'яті: 36,75MB; розмір файлу кешу: 3.3MB

Краще, ніж пакет MSG. І все-таки цей потрібен і для компіляції.

serialize/unserialize

середній час: 477,2 мс; використання пам'яті: 36,25MB; розмір файлу кеша: 5,9 Мб

Чим краще продуктивність, ніж JSON, тим більший масив, тим повільніше json_decode, але ви вже це новий.

Ці зовнішні розширення звужують розмір файлу і здаються чудовими на папері. Цифри не брешуть *. Який сенс компілювати розширення, якщо ви отримаєте майже ті ж результати, що і у стандартної функції PHP?

Ми також можемо зробити висновок, що залежно від ваших потреб ви оберете щось інше, ніж хтось інший:

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

Це все, ще одне порівняння методів серіалізації, яке допоможе вам вибрати той!

* Тестовано з PHPUnit 3.7.31, php 5.5.10 - розшифровується лише за допомогою стандартного жорсткого диска та старого двоядерного процесора - середні цифри на 10 однакових тестах використання, ваші статистичні дані можуть бути різними


Чому б не передати прапор json_decode, щоб примусити повертати масиви?
Олексій Ярошевич

Тому що це повільно. Я цього не тестував, але думаю, що просто примусити змінити тип типу з php швидше.
союка

Я просто знаю, що створювати масиви набагато швидше, ніж об’єкти в php.
Олексій Ярошевич

Отже, ви говорите про це json_decode($object, true), в основному це буде робити те ж саме, (array) json_decode($object)але рекурсивно, так що це буде однакова поведінка, і це матиме значну вартість в обох випадках. Зверніть увагу , що я не тестував продуктивність між подивитися відмінність StdClassі , arrayале це не зовсім точок тут.
союка

Я впевнений, що це ще одна вартість, оскільки це робиться на нижчому рівні без об’єктів.
Олексій Ярошевич

8

Схоже, серіалізація - це та, яку я збираюся використовувати з 2 причин:

  • Хтось зазначив, що несеріалізація швидша, ніж json_decode, а випадок "читання" звучить більш імовірно, ніж випадок "запис".

  • У мене виникли проблеми з json_encode при наявності рядків з недійсними символами UTF-8. Коли це відбувається, рядок закінчується порожнім, що призводить до втрати інформації.


Чи можете ви, будь ласка, детально розглянути свій останній пункт
Naveen Saroye

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; х ++; serialize та json_encode масив_rand $ arr
  • для у <1000; y ++; json_deкодує кодований рядок json - час виклику
  • для у <1000; y ++; unserialize serialized string - calc time
  • відлуння результату, який був швидшим

Під час avase: unserialize вигравав 96 разів за 4 рази json_decode. З авансом приблизно 1,5 мс за 2,5 мс.


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
)

Дійсно, ви праві. Я маю в виду, що це 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 для масиву.
janpio

відповідь невірна. коли використовується 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) Авторські права (c) 1997-2016 Групи PHP Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies із Zend OPcache v7.0.14, Авторські права (c) 1999-2016, від Zend Technologies

І мої результати:

serialize () (win: 999) було приблизно на 10,98% швидше, ніж json_encode () unserialize () (перемоги: 987) було приблизно 33,26% швидше, ніж json_decode () unserialize () (win: 987) було приблизно на 48,35% швидше, ніж масив 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 vs 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>

1

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


2
якщо це просто фій, то краще поставте це як коментар.
технофіл

0

JSON краще, якщо ви хочете створити резервну копію даних та відновити їх на іншій машині або через FTP.

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


0

THX - для цього еталонного коду:

Мої результати по використанню масиву I для конфігурації є покладах: JSON закодовані в 0.0031511783599854 секунд
PHP серіалізовать в 0.0037961006164551 секунд
json_encode()був приблизно 20,47% швидше , ніж serialize() JSON закодовані в 0.0070841312408447 секунд
PHP серіалізовать в 0.0035839080810547 секунд
unserialize()був приблизно 97,66% швидшеjson_encode()

Отже - протестуйте це на власних даних.


Ви маєте на увазі, що json_decode () у "unserialize () був приблизно на 97,66% швидшим, ніж json_encode ()", так?
Meezaan-ud-Din

0

Якщо підсумувати те, що тут говорять люди, json_decode / encode здається швидше, ніж серіалізувати / несеріалізувати, АЛЕ Якщо робити var_dump, тип серіалізованого об'єкта змінюється. Якщо ви чомусь хочете зберегти тип, перейдіть із серіалізацією!

(спробуйте, наприклад, stdClass vs масив)

серіалізувати / несеріалізувати:

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.

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();
?>

-1. Хоча це може бути кращим рішенням, жодна частина цієї відповіді насправді не відповідає на питання ОП. Надалі, можливо, спробуйте відповісти на це запитання, але залиште внизу пропозицію про те, що альтернативне рішення, можливо, варто вивчити.
starbeamrainbowlabs
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.