Preferowana metoda przechowywania tablic PHP (json_encode vs serialize)

609

Potrzebuję przechowywać wielowymiarową asocjacyjną tablicę danych w płaskim pliku do celów buforowania. Czasami mogę spotkać potrzebę przekonwertowania go na JSON do użycia w mojej aplikacji internetowej, ale przez większość czasu będę używać tablicy bezpośrednio w PHP.

Czy bardziej efektywne byłoby przechowywanie tablicy jako JSON lub jako szeregowej tablicy PHP w tym pliku tekstowym? Rozejrzałem się i wydaje mi się, że w najnowszych wersjach PHP (5.3) json_decodejest tak naprawdę szybszy niż unserialize.

Obecnie skłaniam się do przechowywania tablicy jako JSON, ponieważ uważam, że jest łatwiejsza do odczytania przez człowieka, jeśli to konieczne, może być używana zarówno w PHP, jak i JavaScript bez większego wysiłku, a z tego, co przeczytałem, może nawet być szybciej dekodować (choć nie jestem pewien co do kodowania).

Czy ktoś wie o pułapkach? Czy ktoś ma dobre testy porównawcze, które pokazują zalety wydajności obu metod?

KyleFarris
źródło

Odpowiedzi:

563

Zależy od twoich priorytetów.

Jeśli wydajność jest Twoją absolutną cechą jezdną, to na pewno użyj najszybszej. Przed dokonaniem wyboru upewnij się, że w pełni rozumiesz różnice

  • W przeciwieństwie serialize()do tego musisz dodać dodatkowy parametr, aby znaki UTF-8 pozostały nietknięte:json_encode($array, JSON_UNESCAPED_UNICODE) (w przeciwnym razie konwertuje znaki UTF-8 na sekwencje specjalne Unicode).
  • JSON nie będzie pamiętał, jaka była pierwotna klasa obiektu (zawsze są one przywracane jako instancje stdClass).
  • Nie możesz wykorzystać dźwigni __sleep()i __wakeup()przy pomocy JSON
  • Domyślnie tylko właściwości publiczne są serializowane za pomocą JSON. (w PHP>=5.4możesz zaimplementować JsonSerializable aby zmienić to zachowanie).
  • JSON jest bardziej przenośny

I prawdopodobnie jest jeszcze kilka innych różnic, o których nie mogę teraz myśleć.

Prosty test prędkości, aby porównać oba

<?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';
}
Peter Bailey
źródło
31
„JSON konwertuje znaki UTF-8 na sekwencje specjalne Unicode.” Niekoniecznie już prawda: teraz mamy JSON_UNESCAPED_UNICODE.
TRiG
32
Oto prawie 5 lat później i ponownie przeprowadziłem testy (tylko ten json_encode) i jest to średnio około 131% szybciej niż teraz serializacja. Tak więc w wersji 5.4.x w stosunku do wersji 5.3.x trzeba wprowadzić całkiem niezłe ulepszenia tej funkcji W szczególności korzystam z wersji 5.4.24 na CentOS 6. Więc tak, JSON !!
KyleFarris
8
w moim przypadku kodujemy raz i dużo dekodujemy, więc porównaliśmy test json_decode vs unserialize, a wyniki zostały JSON dcodowane w 0,06662392616272 sekund <br> PHP nieserializowane w 0,093269109725952 sekund <br> json_decode () był około 39,99% szybszy niż unserialize ()
AMB
21
Ciekawe: jeśli uruchomisz ten kod na 3v4l.org , najnowsze kompilacje programistyczne PHP7 uruchomią serializację szybciej niż json_encode: „serialize () był około 76,53% szybszy niż json_encode ()”
marcvangend
21
2017, PHP 7.1 iserialize() was roughly 35.04% faster than json_encode()
Elias Soares
239

JSON jest prostszy i szybszy niż format serializacji PHP i powinien być używany, chyba że :

  • Przechowujesz głęboko zagnieżdżone tablice: json_decode()„Ta funkcja zwróci false, jeśli dane zakodowane w JSON są głębsze niż 127 elementów”.
  • Przechowujesz obiekty, które muszą być niezserializowane jako poprawna klasa
  • Współdziałasz ze starymi wersjami PHP, które nie obsługują json_decode
Greg
źródło
12
Świetna odpowiedź. Haha, głębokość 127 poziomów wydaje się trochę szalona; na szczęście idę najwyżej 2-3. Czy masz jakieś dane, aby wykonać kopię zapasową faktu, że json_decode / json_encode jest szybszy niż odserializować / serializować?
KyleFarris
1
Testowałem to jakiś czas temu i json wyszedł szybciej - nie mam już danych.
Greg
47
„5.3.0 Dodano opcjonalną głębokość. Domyślna głębokość rekurencji została zwiększona z 128 do 512”
giorgio79,
4
Dodałbym jeszcze jeden element do powyższej listy: json_encode () nie powinien być używany, jeśli twoje dane mogą zawierać nieprawidłowe sekwencje bajtów UTF-8. Zwraca po prostu fałsz dla takich danych. Spróbuj na przykład: var_dump (json_encode ("\ xEF \ xEF"));
pako
1
To nieprawda, że ​​ogólnie jest szybszy. Jeśli masz małą tablicę z około ~ 500 wpisami, wtedy odserializacja / serializacja jest w rzeczywistości 200-400% szybsza niż json_decode / json_encode (PHP 5.6.19)
Adam
59

Napisałem blog na ten temat: Buforuj dużą tablicę: JSON, serializować czy var_export? . W tym poście pokazano, że serializacja jest najlepszym wyborem dla macierzy od małych do dużych. W przypadku bardzo dużych tablic (> 70 MB) JSON jest lepszym wyborem.

Taco
źródło
8
Link nie jest już dostępny.
Martin Thoma
1
Dzięki, łoś, zaktualizowałem link. Chociaż artykuł ma prawie 6 lat i może nie być tak dokładny w przypadku bieżących wersji PHP.
Taco
Zrobiłem kilka testów i stworzyłem prostą funkcję, aby to przetestować, z dużymi tablicami (dla nich użyto funkcji Petera Baileya) json_encode()jest on około 80% do 150% szybszy (tam naprawdę idzie tam i z góry) niż serialize(), z około 300 iteracjami. Ale kiedy używałem mniejszych tablic ( array("teams" => array(1 => array(4 arrays of players), 2 => array(4 arrays of players)))), testowałem z 750 000 iteracji i w tym przypadku serialize()jest on około 6% do 10% szybszy. Moja funkcja bierze średni czas dla wszystkich iteracji i porównuje je. Mogę opublikować go tutaj jako jedną z odpowiedzi
MiChAeLoKGB
jeśli dane są używane tylko przez PHP, var_export to moja sprawa. Trzeba tylko uważać na ewentualne błędy składniowe w myśli dołączania.
Gfra54
3
blog już nie istnieje
popeye
53

Może Cię również zainteresować https://github.com/phadej/igbinary - który zapewnia inny „silnik” serializacji dla PHP.

Moje losowe / arbitralne dane dotyczące „wydajności” za pomocą PHP 5.3.5 na platformie 64-bitowej pokazują:

JSON:

  • JSON zakodowany w 2.180496931076 sekundach
  • JSON dekodowany w 9.8368630409241 sekund
  • serializowany rozmiar „String”: 13993

Natywny PHP:

  • PHP serializowany w 2,9125759601593 sekund
  • PHP nieserializowane w 6.4348418712616 sekund
  • serializowany rozmiar „String”: 20769

Igbinary:

  • WIN igbinary zserializowany w 1.6099879741669 sekund
  • WIN igbinrary niezserializowany w 4,7737920284271 sekund
  • WIN zserializowany „ciąg” Rozmiar: 4467

Szybsze jest więc igbinary_serialize () i igbinary_unserialize () i zużywa mniej miejsca na dysku.

Użyłem kodu fillArray (0, 3) jak powyżej, ale wydłużyłem klucze tablicy.

igbinary może przechowywać te same typy danych, co natywna serializacja PHP (więc nie ma problemu z obiektami itp.) i możesz powiedzieć PHP5.3, aby używał go do obsługi sesji, jeśli chcesz.

Zobacz także http://ilia.ws/files/zendcon_2010_hidden_features.pdf - w szczególności slajdy 14/15/16

David Goodwin
źródło
25

Właśnie przetestowałem serializację i kodowanie i dekodowanie json, plus rozmiar, jaki zajmie zapisany ciąg.

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

Możemy dojść do wniosku, że JSON koduje szybciej i daje mniejszy ciąg, ale odserializacja jest szybsza w dekodowaniu łańcucha.

Blunk
źródło
6
Nie wiem, dlaczego ludzie zawsze przeprowadzają testy wydajności przy tak małym zestawie danych. Dzięki temu masz wszystkie koszty ogólne, które powodują błędy w wynikach. A jeśli ludzie są zainteresowani wydajnością, to prawdopodobnie dlatego, że mają bardzo duży zestaw danych, ponieważ nie ma sensu uzyskiwać mikro sekundy.
Yann Sagon
1
Dość często iteruję wiele małych zestawów danych. Przy setkach małych zestawów danych, uzyskanie 1 ms dla każdego z nich jest nadal interesujące.
Teson
@YannSagon Nawet przy małych zestawach danych sensowne jest wykonanie testu wydajności. Skąd powinieneś wiedzieć przed testem, czy jest to tylko jedna mikrosekunda?
Adam,
17

Jeśli buforujesz informacje, które ostatecznie chcesz „dołączyć” w późniejszym czasie, możesz spróbować użyć var_export . W ten sposób trafiasz tylko w „serializuj”, a nie w „odserializuj”.

Jordan S. Jones
źródło
Jest to prawdopodobnie najszybszy możliwy sposób. Napisałem przykład na SO „PHP - szybkie serializowanie / odserializowanie”: stackoverflow.com/questions/2545455/…
dave1010
12

Rozszerzyłem test, aby uwzględnić wydajność bezserializacji. Oto liczby, które mam.

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

Więc json wydaje się być szybszy do kodowania, ale powolny w dekodowaniu. Może to zależeć od twojej aplikacji i tego, czego oczekujesz najbardziej.

Jeff Whiting
źródło
9

Naprawdę fajny temat i po przeczytaniu kilku odpowiedzi chcę podzielić się moimi eksperymentami na ten temat.

Dostałem przypadek użycia, w którym niemal za każdym razem, gdy rozmawiam z bazą danych, trzeba zapytać o „ogromną” tabelę (nie pytaj dlaczego, tylko fakt). System buforowania bazy danych nie jest odpowiedni, ponieważ nie buforuje różnych żądań, więc pomyślałem o systemach buforowania php.

Próbowałem, apcuale nie pasowało do potrzeb, pamięć nie jest w tym przypadku wystarczająco niezawodna. Następnym krokiem było umieszczenie w pamięci podręcznej pliku z serializacją.

Tabela zawiera 14355 pozycji z 18 kolumnami, są to moje testy i statystyki dotyczące odczytu zserializowanej pamięci podręcznej:

JSON:

Jak wszyscy powiedzieliście, główną niedogodnością związaną z json_encode/ json_decodejest to, że przekształca wszystko w StdClassinstancję (lub obiekt). Jeśli potrzebujesz go zapętlić, prawdopodobnie zrobisz to, przekształcając go w tablicę, i tak, to wydłuża czas transformacji

średni czas: 780,2 ms; wykorzystanie pamięci: 41,5 MB; rozmiar pliku pamięci podręcznej: 3,8 MB

Msgpack

@hutch wspomina o msgpack . Ładna strona internetowa. Spróbujmy, prawda?

średni czas: 497 ms; wykorzystanie pamięci: 32 MB; rozmiar pliku pamięci podręcznej: 2,8 MB

To lepiej, ale wymaga nowego rozszerzenia; kompilowanie czasem przestraszonych ludzi ...

IgBinary

@ GingerDog wspomina o igbinary . Zauważ, że ustawiłem, igbinary.compact_strings=Offponieważ bardziej zależy mi na wydajności czytania niż na rozmiarze pliku.

średni czas: 411,4 ms; wykorzystanie pamięci: 36,75 MB; rozmiar pliku pamięci podręcznej: 3,3 MB

Lepsze niż paczka msg. Jednak ten także wymaga kompilacji.

serialize/unserialize

średni czas: 477,2 ms; wykorzystanie pamięci: 36,25 MB; rozmiar pliku pamięci podręcznej: 5,9 MB

Im lepsza wydajność niż JSON, tym większa matryca, wolniejsza json_decode, ale już to nowe.

Te rozszerzenia zewnętrzne zmniejszają rozmiar pliku i wydają się świetne na papierze. Liczby nie kłamią *. Po co kompilować rozszerzenie, jeśli uzyskasz prawie takie same wyniki, jak w przypadku standardowej funkcji PHP?

Możemy również wywnioskować, że w zależności od potrzeb wybierzesz coś innego niż ktoś inny:

  • IgBinary jest naprawdę fajny i działa lepiej niż MsgPack
  • Msgpack lepiej kompresuje twoje dane (zauważ, że nie wypróbowałem opcji igbinary compact.string).
  • Nie chcesz kompilować? Użyj standardów.

To wszystko, kolejne porównanie metod serializacji, które pomogą ci wybrać tę!

* Testowane z PHPUnit 3.7.31, php 5.5.10 - tylko dekodowanie ze standardowym dyskiem twardym i starym dwurdzeniowym procesorem - średnie liczby w 10 takich samych testach przypadków użycia, twoje statystyki mogą być inne

soja
źródło
Dlaczego nie przekazać flagi do json_decode, aby wymusić zwracanie tablic?
Alex Yaroshevich
Ponieważ jest wolny. Nie testowałem tego, ale myślę, że wymuszenie zmiany typu z php jest szybsze.
soyuka
Wiem tylko, że tworzenie tablic znacznie szybciej niż obiektów w php.
Alex Yaroshevich
Mówiąc o tym json_decode($object, true), w zasadzie zrobi to samo, (array) json_decode($object)ale rekurencyjnie, więc byłoby to takie samo zachowanie i będzie miało znaczny koszt w obu przypadkach. Zauważ, że nie testowałem dyferencjału między wydajnością StdClassa arrayale to naprawdę nie jest punktem tutaj.
soyuka
Jestem pewien, że to kolejny koszt, ponieważ odbywa się na niższym poziomie bez obiektów.
Alex Yaroshevich
8

Wydaje się, że serializacja jest tym, którego zamierzam użyć z 2 powodów:

  • Ktoś zauważył, że odserializacja jest szybsza niż json_decode, a przypadek „odczytu” wydaje się bardziej prawdopodobny niż przypadek „zapisu”.

  • Mam problem z json_encode, gdy mam ciągi znaków z nieprawidłowymi znakami UTF-8. Kiedy tak się dzieje, łańcuch zostaje pusty, co powoduje utratę informacji.

urraka
źródło
czy możesz
opisać
6

Testowałem to bardzo dokładnie na dość złożonym, lekko zagnieżdżonym multi-hash z wszystkimi rodzajami danych (string, NULL, liczby całkowite), a serializacja / deserializacja zakończyła się znacznie szybciej niż json_encode / json_decode.

Jedyną zaletą, jaką Json miał w moich testach, był mniejszy „zapakowany” rozmiar.

Odbywa się to w PHP 5.3.3, daj mi znać, jeśli chcesz więcej szczegółów.

Oto wyniki testów, a następnie kod do ich wytworzenia. Nie mogę dostarczyć danych testowych, ponieważ ujawniłyby one informacje, których nie mogę wypuścić na wolności.

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!';
}
Mr. Sox
źródło
Właśnie wykonałem podobny test z PHP 5.4.12 i znalazłem podobne wyniki: {un,} serializacja jest szybsza. Moje dane to skróty zagnieżdżone na 3 poziomach głębokości (z serializacją 900 000).
sorpigal,
6

Zrobiłem też mały test porównawczy. Moje wyniki były takie same. Ale potrzebuję wydajności dekodowania. Tam, gdzie zauważyłem, podobnie jak kilka wyżej wspomnianych osób, unserializejest szybsze niż json_decode. unserializezajmuje około 60-70% json_decodeczasu. Wniosek jest więc dość prosty: kiedy potrzebujesz wydajności kodowania, używaj json_encode, kiedy potrzebujesz wydajności dekodowania, używaj unserialize. Ponieważ nie można połączyć tych dwóch funkcji, musisz dokonać wyboru, w którym potrzebujesz większej wydajności.

Mój punkt odniesienia w pseudo:

  • Zdefiniuj tablicę $ arr za pomocą kilku losowych kluczy i wartości
  • dla x <100; x ++; serializuj i json_encode tablica_rand $ arr
  • dla y <1000; y ++; json_decode ciąg zakodowany w jsonie - czas obliczeniowy
  • dla y <1000; y ++; odserializować serializowany ciąg - czas obliczeniowy
  • powtórz wynik, który był szybszy

On avarage: unserialize wygrał 96 razy ponad 4 razy kod json_decode. Średni czas około 1,5 ms ponad 2,5 ms.

Jelmer
źródło
3

Przed podjęciem ostatecznej decyzji należy pamiętać, że format JSON nie jest bezpieczny dla tablic asocjacyjnych - json_decode()zamiast tego zwróci je jako obiekty:

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

Dane wyjściowe to:

Array
(
    [Frodo] => hobbit
    [Gimli] => dwarf
    [Gandalf] => wizard
)
stdClass Object
(
    [Frodo] => hobbit
    [Gimli] => dwarf
    [Gandalf] => wizard
)
za dużo php
źródło
Rzeczywiście masz rację. To znaczy, to jest JavaScript obiekt notacja przecież! Na szczęście, jeśli wiesz, że to, co zakodowałeś, json_encodeto tablica asocjacyjna, możesz łatwo zmusić ją z powrotem do tablicy w taki sposób: $json = json_encode($some_assoc_array); $back_to_array = (array)json_decode($json);Warto również zauważyć, że możesz uzyskać dostęp do obiektów w taki sam sposób jak tablice w PHP, więc w typowym scenariuszu, nie wiadomo nawet różnicy. Dobra uwaga!
KyleFarris,
30
@toomuchphp, przepraszam, ale się mylisz. Istnieje drugi parametr dla json_decode 'bool $ assoc = false', który powoduje, że json_decode tworzy tablicę. @KyleFarris, powinno to również być szybsze niż użycie typecast do tablic.
janpio
odpowiedź jest nieprawidłowa. przy użyciu true jako drugiego parametru funkcji, json_decode () zwróci tablice asocjacyjne zamiast obiektów.
Marvin Saldinger,
3

Po pierwsze, zmieniłem skrypt, aby wykonać więcej testów porównawczych (a także wykonać 1000 uruchomień zamiast tylko 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';
}

Użyłem tej wersji PHP 7:

PHP 7.0.14 (cli) (zbudowany: 18 stycznia 2017 19:13:23) (NTS) Copyright (c) 1997-2016 The PHP Group Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies z Zend OPcache 7.0.0, Copyright (c) 1999-2016, autor: Zend Technologies

A moje wyniki to:

serialize () (wygrane: 999) było około 10,98% szybsze niż json_encode () unserialize () (wygrane: 987) było około 33,26% szybsze niż json_decode () unserialize () (wygrane: 987) było około 48,35% szybsze niż tablica json_decode ()

Tak wyraźnie , serialize / unserialize to najszybsza metoda, natomiast json_encode / dekodowania jest najbardziej przenośny.

Jeśli weźmiesz pod uwagę scenariusz, w którym odczytujesz / zapisujesz dane szeregowane 10 razy lub częściej niż musisz wysyłać lub odbierać z systemu innego niż PHP, WCIĄŻ lepiej jest użyć serializacji / odserializować i mieć json_encode lub json_decode przed serializacją pod względem czasu.

Shawn Tolidano
źródło
2

Sprawdź wyniki tutaj (przepraszam za włamanie do umieszczenia kodu PHP w polu kodu JS):

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

WYNIKI: serialize()i unserialize()oba są znacznie szybsze w PHP 5.4 na tablicach o różnej wielkości.

Zrobiłem skrypt testowy na rzeczywistych danych do porównywania json_encode vs serialize i json_decode vs unserialize. Test został przeprowadzony w systemie buforowania witryny e-commerce w produkcji. Po prostu bierze dane już znajdujące się w pamięci podręcznej i testuje czasy kodowania / dekodowania (lub serializacji / odserializowania) wszystkich danych, a ja umieszczam je w łatwo widocznej tabeli.

Uruchomiłem to na dzielonym serwerze hostingowym PHP 5.4.

Wyniki były bardzo rozstrzygające, że dla tych dużych i małych zestawów danych serializowanie i odserializowanie były wyraźnymi zwycięzcami. W szczególności w moim przypadku użycia, json_decode i unserialize są najważniejsze dla systemu buforowania. Unserialize był tutaj niemal wszechobecnym zwycięzcą. Zazwyczaj było to 2 do 4 razy (czasem 6 lub 7 razy) tak szybko, jak json_decode.

Warto zauważyć różnicę w wynikach z @ peter-bailey.

Oto kod PHP używany do generowania wyników:

<?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
źródło
1

po prostu fyi - jeśli chcesz serializować swoje dane do czegoś łatwego do odczytania i zrozumienia, takiego jak JSON, ale z większą kompresją i wyższą wydajnością, powinieneś sprawdzić pakiet wiadomości.

Niecka
źródło
2
jeśli to tylko fyi, lepiej zostaw to jako komentarz.
technofil,
0

JSON jest lepszy, jeśli chcesz wykonać kopię zapasową danych i przywrócić ją na innym komputerze lub przez FTP.

Na przykład z serializacją, jeśli przechowujesz dane na serwerze Windows, pobierz je przez FTP i przywróć na Linuksie, który nie mógłby już działać z powodu ponownego kodowania charachtera, ponieważ serializacja przechowuje długość łańcuchów i w Unicode > Transkodowanie UTF-8 około 1 bajtowego charachtera może mieć długość 2 bajtów, co powoduje awarię algorytmu.

Informate.it
źródło
0

THX - dla tego kodu testu porównawczego:

Moje wyniki w tablicy, której używam do konfiguracji, są następujące: JSON zakodowany w 0,0031511783599854 sekund
PHP serializowany w 0,0037961006164551 sekund
json_encode()był około 20,47% szybszy niż serialize() JSON zakodowany w 0,0070841312408447 sekund
PHP serializowany w 0,0035839080810547 sekund
unserialize()był około 97,66% szybszy niżjson_encode()

Więc - przetestuj na własnych danych.

mk182
źródło
Masz na myśli, że json_decode () w „unserialize () był około 97,66% szybszy niż json_encode ()”, tak?
Meezaan-ud-Din
0

Jeśli podsumowując to, co mówią ludzie, json_decode / encode wydaje się szybszy niż serializacja / unserializuj ALE Jeśli zrobisz var_dump, typ serializowanego obiektu zostanie zmieniony. Jeśli z jakiegoś powodu chcesz zachować ten typ, skorzystaj z serializacji!

(spróbuj na przykład stdClass vs array)

serializuj / odserializuj:

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 encode / decode

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]

Jak widać, json_encode / decode konwertuje wszystko na stdClass, co nie jest aż tak dobre, informacje o obiektach są tracone ... Więc decyduj na podstawie potrzeb, szczególnie jeśli nie są to tylko tablice ...

David Constantine
źródło
Tylko uwaga: większość innych odpowiedzi mówi, że serializacja / odserializowanie jest szybsze.
Ecker00
-3

Sugeruję, abyś użył Super Cache, która jest mechanizmem buforowania plików, który nie użyje json_encodelub serialize. Jest prosty w użyciu i bardzo szybki w porównaniu do innych mechanizmów PHP Cache.

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

Dawny:

<?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();
?>
szabla
źródło
-1. Chociaż może to być lepsze rozwiązanie, żadna część tej odpowiedzi nie odpowiada na pytanie PO. W przyszłości może spróbuj odpowiedzieć na pytanie, pozostawiając na dole sugestię, że alternatywne rozwiązanie może być warte zbadania.
starbeamrainbowlabs