Bevorzugte Methode zum Speichern von PHP-Arrays (json_encode vs serialize)

608

Ich muss ein mehrdimensionales assoziatives Datenarray für Caching-Zwecke in einer flachen Datei speichern. Es kann gelegentlich vorkommen, dass ich es zur Verwendung in meiner Web-App in JSON konvertieren muss, aber die meiste Zeit werde ich das Array direkt in PHP verwenden.

Wäre es effizienter, das Array als JSON oder als serialisiertes PHP-Array in dieser Textdatei zu speichern? Ich habe mich umgesehen und es scheint, dass in den neuesten Versionen von PHP (5.3) json_decodetatsächlich schneller ist als unserialize.

Ich neige derzeit dazu, das Array als JSON zu speichern, da ich der Meinung bin, dass es bei Bedarf von einem Menschen leichter gelesen werden kann. Es kann mit sehr geringem Aufwand sowohl in PHP als auch in JavaScript verwendet werden, und nach dem, was ich gelesen habe, könnte es sogar sein schneller zu dekodieren (nicht sicher über die Kodierung).

Kennt jemand irgendwelche Fallstricke? Hat jemand gute Benchmarks, um die Leistungsvorteile beider Methoden aufzuzeigen?

KyleFarris
quelle

Antworten:

563

Kommt auf deine Prioritäten an.

Wenn Leistung Ihre absolute Fahrcharakteristik ist, verwenden Sie auf jeden Fall die schnellste. Stellen Sie einfach sicher, dass Sie die Unterschiede vollständig verstanden haben, bevor Sie eine Wahl treffen

  • Im Gegensatz serialize()dazu müssen Sie zusätzliche Parameter hinzufügen, um UTF-8-Zeichen unberührt zu lassen: json_encode($array, JSON_UNESCAPED_UNICODE) (Andernfalls werden UTF-8-Zeichen in Unicode-Escape-Sequenzen konvertiert.)
  • JSON hat keine Erinnerung an die ursprüngliche Klasse des Objekts (sie werden immer als Instanzen von stdClass wiederhergestellt).
  • Sie können __sleep()und __wakeup()mit JSON nicht nutzen
  • Standardmäßig werden nur öffentliche Eigenschaften mit JSON serialisiert. (In können PHP>=5.4Sie JsonSerializable implementieren , um dieses Verhalten zu ändern.)
  • JSON ist portabler

Und es gibt wahrscheinlich noch ein paar andere Unterschiede, an die ich im Moment nicht denken kann.

Ein einfacher Geschwindigkeitstest, um die beiden zu vergleichen

<?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
quelle
31
"JSON konvertiert UTF-8-Zeichen in Unicode-Escape-Sequenzen." Nicht mehr unbedingt wahr: wir haben jetzt JSON_UNESCAPED_UNICODE.
TRiG
32
Hier sind wir fast 5 Jahre später und ich habe die Tests erneut durchgeführt (nur die json_encode) und es ist durchschnittlich 131% schneller als jetzt serialisieren. Es muss also einige nette Verbesserungen an dieser Funktion in 5.4.x gegenüber 5.3.x geben. Insbesondere verwende ich 5.4.24 unter CentOS 6. Also, yay für JSON !!
KyleFarris
8
In meinem Fall haben wir einmal codiert und viel decodiert, also haben wir den json_decode mit unseremialisiert verglichen und die Ergebnisse wurden in 0,06662392616272 Sekunden JSON-codiert. <br> PHP unserialisiert in 0,093269109725952 Sekunden <br> json_decode () war ungefähr 39,99% schneller als unserialize ()
AMB
21
Interessant: Wenn Sie diesen Code auf 3v4l.org ausführen , werden die neuesten PHP7-Entwicklungs-Builds schneller serialisiert als json_encode: "serialize () war ungefähr 76,53% schneller als json_encode ()"
marcvangend
21
2017, PHP 7.1 undserialize() was roughly 35.04% faster than json_encode()
Elias Soares
239

JSON ist einfacher und schneller als das Serialisierungsformat von PHP und sollte verwendet werden, es sei denn :

  • Sie speichern tief verschachtelte Arrays :: json_decode()"Diese Funktion gibt false zurück, wenn die JSON-codierten Daten tiefer als 127 Elemente sind."
  • Sie speichern Objekte, die unserialisiert werden müssen, als die richtige Klasse
  • Sie interagieren mit alten PHP-Versionen, die json_decode nicht unterstützen
Greg
quelle
12
Gute Antwort. Haha, 127 Level tief scheint ein bisschen verrückt zu sein; Zum Glück gehe ich höchstens 2-3. Haben Sie Daten, um die Tatsache zu sichern, dass json_decode / json_encode schneller ist als unserialize / serialize?
KyleFarris
1
Ich habe es vor einiger Zeit getestet und json kam schneller heraus - ich habe die Daten jedoch nicht mehr.
Greg
47
"5.3.0 Die optionale Tiefe wurde hinzugefügt. Die Standard-Rekursionstiefe wurde von 128 auf 512 erhöht"
giorgio79
4
Ich würde der obigen Liste ein weiteres Element hinzufügen: json_encode () sollte nicht verwendet werden, wenn Ihre Daten möglicherweise ungültige UTF-8-Byte-Sequenzen enthalten. Für solche Daten wird einfach false zurückgegeben. Versuchen Sie zum Beispiel: var_dump (json_encode ("\ xEF \ xEF"));
Pako
2
Es ist nicht wahr, dass es im Allgemeinen schneller ist. Wenn Sie ein kleines Array mit ca. 500 Einträgen haben, ist unserialize / serialize tatsächlich 200-400% schneller als json_decode / json_encode (PHP 5.6.19)
Adam
59

Ich habe einen Blogpost zu diesem Thema geschrieben: " Ein großes Array zwischenspeichern: JSON, serialize oder var_export? " . In diesem Beitrag wird gezeigt, dass Serialisierung die beste Wahl für kleine bis große Arrays ist. Für sehr große Arrays (> 70 MB) ist JSON die bessere Wahl.

Taco
quelle
8
Der Link ist nicht mehr verfügbar.
Martin Thoma
1
Danke, Elch, ich habe den Link aktualisiert. Obwohl der Artikel fast 6 Jahre alt ist und für aktuelle PHP-Versionen möglicherweise nicht so genau ist.
Taco
Ich habe einige Tests durchgeführt und eine einfache Funktion zum Testen erstellt. Mit großen Arrays (für die die Funktion von Peter Bailey verwendet wird) json_encode()ist die Funktion etwa 80% bis 150% schneller (sie geht dort wirklich auf und ab) als serialize()mit etwa 300 Iterationen. Bei Verwendung der kleineren Arrays ( array("teams" => array(1 => array(4 arrays of players), 2 => array(4 arrays of players)))) habe ich jedoch mit 750.000 Iterationen getestet und bin in diesem Fall serialize()etwa 6% bis 10% schneller. Meine Funktion nimmt die Durchschnittszeiten für alle Iterationen und vergleicht sie. Ich könnte es hier als eine der Antworten
posten
Wenn die Daten nur von PHP verwendet werden, ist var_export mein Ding. Sie müssen nur vorsichtig mit möglichen Syntaxfehlern im Include-Gedanken sein.
Gfra54
3
Blog existiert nicht mehr
Popeye
53

Sie könnten auch an https://github.com/phadej/igbinary interessiert sein - das eine andere Serialisierungs-Engine für PHP bietet.

Meine zufälligen / willkürlichen Leistungszahlen mit PHP 5.3.5 auf einer 64-Bit-Plattform zeigen:

JSON:

  • JSON in 2.180496931076 Sekunden codiert
  • JSON in 9,8368630409241 Sekunden dekodiert
  • serialisierte "String" Größe: 13993

Natives PHP:

  • PHP in 2,9125759601593 Sekunden serialisiert
  • PHP unserialisiert in 6.4348418712616 Sekunden
  • serialisierte "String" Größe: 20769

Igbinary:

  • WIN igbinary serialisiert in 1.6099879741669 Sekunden
  • WIN igbinrary unserialisiert in 4.7737920284271 Sekunden
  • WIN serialisiert "String" Größe: 4467

Es ist also schneller, igbinary_serialize () und igbinary_unserialize () zu verwenden, und es wird weniger Speicherplatz benötigt.

Ich habe den Code fillArray (0, 3) wie oben verwendet, aber die Array-Schlüssel zu längeren Zeichenfolgen gemacht.

igbinary kann dieselben Datentypen speichern wie die native Serialisierung von PHP (also kein Problem mit Objekten usw.), und Sie können PHP5.3 anweisen, es für die Sitzungsbehandlung zu verwenden, wenn Sie dies wünschen.

Siehe auch http://ilia.ws/files/zendcon_2010_hidden_features.pdf - speziell Folien 14/15/16

David Goodwin
quelle
25

Y hat gerade die serialisierte und json-Codierung und -Decodierung sowie die Größe der gespeicherten Zeichenfolge getestet.

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

Wir können daraus schließen, dass JSON schneller codiert und eine kleinere Zeichenfolge ergibt, aber unserialize die Zeichenfolge schneller decodiert.

Blunk
quelle
6
Ich weiß nicht, warum Leute immer Leistungstests mit so kleinen Datenmengen durchführen. Auf diese Weise haben Sie den gesamten Aufwand, der Ihren Ergebnissen Fehler hinzufügt. Und wenn Leute an Leistung interessiert sind, liegt das wahrscheinlich daran, dass sie einen sehr großen Datensatz haben, weil es keinen Sinn macht, einmal eine Mikrosekunde zu gewinnen.
Yann Sagon
1
Sehr oft iteriere ich über viele kleine Datensätze. Bei Hunderten kleiner Datensätze ist es immer noch interessant, für jeden Datensatz 1 ms zu gewinnen.
Teson
@YannSagon Auch bei kleinen Datenmengen ist es sinnvoll, einen Leistungstest durchzuführen. Woher sollten Sie vor dem Test wissen, ob es sich nur um eine Mikrosekunde handelt?
Adam
17

Wenn Sie Informationen zwischenspeichern, die Sie zu einem späteren Zeitpunkt letztendlich "einschließen" möchten, sollten Sie versuchen, var_export zu verwenden . Auf diese Weise erhalten Sie den Treffer nur in der "Serialisierung" und nicht in der "Unserialisierung".

Jordan S. Jones
quelle
Dies ist höchstwahrscheinlich der schnellste Weg. Ich habe ein Beispiel für die SO "PHP - Fast Serialize / Unserialize" geschrieben: stackoverflow.com/questions/2545455/…
dave1010
12

Ich habe den Test um die Leistung unserer Unserialisierung erweitert. Hier sind die Zahlen, die ich bekommen habe.

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 scheint also schneller für die Codierung zu sein, aber langsam für die Decodierung. Es kann also von Ihrer Anwendung abhängen und davon, was Sie am meisten erwarten.

Jeff Whiting
quelle
9

Wirklich schönes Thema und nachdem ich die wenigen Antworten gelesen habe, möchte ich meine Experimente zu diesem Thema teilen.

Ich habe einen Anwendungsfall, in dem fast jedes Mal, wenn ich mit der Datenbank spreche, eine "riesige" Tabelle abgefragt werden muss (fragen Sie nicht warum, nur eine Tatsache). Das Datenbank-Caching-System ist nicht geeignet, da es die verschiedenen Anforderungen nicht zwischenspeichert. Daher habe ich über PHP-Caching-Systeme nachgedacht.

Ich habe es versucht, apcuaber es passte nicht zu den Anforderungen. Der Speicher ist in diesem Fall nicht zuverlässig genug. Der nächste Schritt bestand darin, eine Datei mit Serialisierung zwischenzuspeichern.

Die Tabelle enthält 14355 Einträge mit 18 Spalten. Dies sind meine Tests und Statistiken zum Lesen des serialisierten Caches:

JSON:

Wie Sie alle sagten, besteht die größte Unannehmlichkeit bei json_encode/ json_decodedarin, dass alles in eine StdClassInstanz (oder ein Objekt) umgewandelt wird. Wenn Sie es schleifen müssen, werden Sie es wahrscheinlich in ein Array umwandeln, und ja, es erhöht die Umwandlungszeit

durchschnittliche Zeit: 780,2 ms; Speichernutzung: 41,5 MB; Cache-Dateigröße: 3,8 MB

Msgpack

@ Hutch erwähnt msgpack . Hübsche Website. Probieren wir es aus.

durchschnittliche Zeit: 497 ms; Speichernutzung: 32 MB; Cache-Dateigröße: 2,8 MB

Das ist besser, erfordert aber eine neue Erweiterung. manchmal ängstliche Menschen zusammenstellen ...

IgBinary

@ GingerDog erwähnt igbinary . Beachten Sie, dass ich das festgelegt habe, igbinary.compact_strings=Offweil mir die Leseleistung wichtiger ist als die Dateigröße.

durchschnittliche Zeit: 411,4 ms; Speichernutzung: 36,75 MB; Cache-Dateigröße: 3,3 MB

Besser als msg pack. Dies erfordert jedoch auch das Kompilieren.

serialize/.unserialize

durchschnittliche Zeit: 477,2 ms; Speichernutzung: 36,25 MB; Cache-Dateigröße: 5,9 MB

Bessere Leistungen als JSON, je größer das Array ist, desto langsamer json_decodeist es, aber das ist Ihnen bereits neu.

Diese externen Erweiterungen verringern die Dateigröße und scheinen auf dem Papier großartig zu sein. Zahlen lügen nicht *. Was bringt es, eine Erweiterung zu kompilieren, wenn Sie fast die gleichen Ergebnisse erzielen, die Sie mit einer Standard-PHP-Funktion erzielen würden?

Wir können auch ableiten, dass Sie je nach Ihren Bedürfnissen etwas anderes wählen als jemand anderes:

  • IgBinary ist wirklich nett und bietet eine bessere Leistung als MsgPack
  • Msgpack kann Ihre Daten besser komprimieren (beachten Sie, dass ich die Option igbinary compact.string nicht ausprobiert habe).
  • Willst du nicht kompilieren? Verwenden Sie Standards.

Das war's, ein weiterer Vergleich der Serialisierungsmethoden, der Ihnen bei der Auswahl hilft!

* Getestet mit PHPUnit 3.7.31, PHP 5.5.10 - nur Dekodierung mit einer Standard-Festplatte und einer alten Dual-Core-CPU - durchschnittliche Anzahl bei 10 gleichen Anwendungsfalltests, Ihre Statistiken können unterschiedlich sein

Sojuka
quelle
Warum nicht das Flag an json_decode übergeben, um die Rückgabe von Arrays zu erzwingen?
Alex Yaroshevich
Weil es langsam ist. Ich habe das nicht getestet, aber ich denke, dass es schneller ist, einfach den Typwechsel von PHP zu erzwingen.
Sojuka
Ich weiß nur, dass das Erstellen von Arrays viel schneller ist als das von Objekten in PHP.
Alex Yaroshevich
Sie sprechen also davon json_decode($object, true), dass es im Grunde das Gleiche tut, (array) json_decode($object)aber rekursiv, so dass dies das gleiche Verhalten wäre und in beiden Fällen erhebliche Kosten verursacht. Beachten Sie, dass ich keine Leistungsunterschiede zwischen StdClassund getestet habe, arrayaber das ist hier nicht wirklich der Punkt.
Sojuka
Ich bin sicher, es sind weitere Kosten, da dies auf einer niedrigeren Ebene ohne Objekte erfolgt.
Alex Yaroshevich
8

Scheint, als würde serialize aus zwei Gründen verwendet:

  • Jemand wies darauf hin, dass unserialize schneller ist als json_decode und ein 'read'-Fall wahrscheinlicher klingt als ein' write'-Fall.

  • Ich hatte Probleme mit json_encode, wenn Zeichenfolgen mit ungültigen UTF-8-Zeichen vorhanden waren. In diesem Fall ist die Zeichenfolge leer und führt zu Informationsverlust.

Urraka
quelle
Können
6

Ich habe dies sehr gründlich an einem ziemlich komplexen, leicht verschachtelten Multi-Hash mit allen Arten von Daten (String, NULL, Ganzzahlen) getestet, und Serialize / Unserialize endete viel schneller als json_encode / json_decode.

Der einzige Vorteil, den json in meinen Tests hatte, war die kleinere Größe.

Diese werden unter PHP 5.3.3 durchgeführt. Lassen Sie mich wissen, wenn Sie weitere Details wünschen.

Hier sind Testergebnisse und dann der Code, um sie zu erzeugen. Ich kann die Testdaten nicht bereitstellen, da sie Informationen enthalten, die ich nicht in freier Wildbahn veröffentlichen darf.

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
quelle
Ich habe gerade einen ähnlichen Test mit PHP 5.4.12 durchgeführt und ähnliche Ergebnisse gefunden: {un,} serialize ist schneller. Meine Daten sind Hashes, die 3 Ebenen tief verschachtelt sind (900.000 serialisiert).
Sorpigal
6

Ich habe auch einen kleinen Benchmark gemacht. Meine Ergebnisse waren die gleichen. Aber ich brauche die Dekodierungsleistung. Wo ich bemerkt habe, wie ein paar Leute oben auch sagten, unserializeist schneller als json_decode. unserializedauert ungefähr 60-70% der json_decodeZeit. Die Schlussfolgerung ist also ziemlich einfach: Wenn Sie Leistung beim Codieren benötigen, verwenden Sie json_encode, wenn Sie Leistung beim Decodieren benötigen, verwenden Sie unserialize. Da Sie die beiden Funktionen nicht zusammenführen können, müssen Sie eine Auswahl treffen, bei der Sie mehr Leistung benötigen.

Mein Benchmark in Pseudo:

  • Definieren Sie das Array $ arr mit einigen zufälligen Schlüsseln und Werten
  • für x <100; x ++; serialize und json_encode ein array_rand von $ arr
  • für y <1000; y ++; json_decode die json-codierte Zeichenfolge - Berechnungszeit
  • für y <1000; y ++; unserialisieren Sie die serialisierte Zeichenfolge - Berechnungszeit
  • Echo das Ergebnis, das schneller war

Im Durchschnitt: unserialize hat 96-mal über 4-mal den json_decode gewonnen. Mit einem Durchschnitt von ungefähr 1,5 ms über 2,5 ms.

Jelmer
quelle
3

Bevor Sie Ihre endgültige Entscheidung treffen, beachten Sie, dass das JSON-Format für assoziative Arrays nicht sicher ist. json_decode()Stattdessen werden sie als Objekte zurückgegeben:

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

Ausgabe ist:

Array
(
    [Frodo] => hobbit
    [Gimli] => dwarf
    [Gandalf] => wizard
)
stdClass Object
(
    [Frodo] => hobbit
    [Gimli] => dwarf
    [Gandalf] => wizard
)
zu viel php
quelle
In der Tat haben Sie recht. Ich meine, es ist Javascript - Objekt - Notation afterall! Wenn Sie wissen, dass das, was Sie mit json_encodeeinem assoziativen Array codiert haben, es glücklicherweise wie folgt in ein Array zurückzwingen kann: $json = json_encode($some_assoc_array); $back_to_array = (array)json_decode($json);Beachten Sie außerdem, dass Sie in einem typischen Szenario auf Objekte wie auf Arrays in PHP zugreifen können. man würde nicht einmal den Unterschied kennen. Guter Punkt!
KyleFarris
30
@toomuchphp, sorry aber du liegst falsch. Es gibt einen zweiten Parameter für json_decode 'bool $ assoc = false', mit dem json_decode ein Array erzeugt. @KyleFarris, dies sollte auch schneller sein als die Verwendung des Typecasts zum Array.
Janpio
Die Antwort ist nicht richtig. Bei Verwendung von true als zweitem Funktionsparameter gibt json_decode () assoziative Arrays anstelle von Objekten zurück.
Marvin Saldinger
3

Zuerst habe ich das Skript geändert, um mehr Benchmarking durchzuführen (und auch 1000 Läufe statt nur 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';
}

Ich habe diesen Build von PHP 7 verwendet:

PHP 7.0.14 (cli) (erstellt: 18. Januar 2017, 19:13:23 Uhr) (NTS) Copyright (c) 1997-2016 Die PHP Group Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies mit Zend OPcache v7.0.14, Copyright (c) 1999-2016, von Zend Technologies

Und meine Ergebnisse waren:

serialize () (Gewinne: 999) war ungefähr 10,98% schneller als json_encode () unserialize () (Gewinne: 987) war ungefähr 33,26% schneller als json_decode () unserialize () (Gewinne: 987) war ungefähr 48,35% schneller als Array json_decode ()

Serialize / unserialize ist also eindeutig die schnellste Methode, während json_encode / decode die portabelste ist.

Wenn Sie ein Szenario in Betracht ziehen, in dem Sie serialisierte Daten 10x oder öfter lesen / schreiben, als Sie an ein Nicht-PHP-System senden oder von diesem empfangen müssen, ist es NOCH besser, serialize / unserialize zu verwenden und es vor der Serialisierung mit json_encode oder json_decode zu versehen in Bezug auf die Zeit.

Shawn Tolidano
quelle
2

Schauen Sie sich die Ergebnisse hier an (entschuldigen Sie den Hack, der den PHP-Code in das JS-Code-Feld gestellt hat):

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

ERGEBNISSE: serialize()und unserialize()beide sind in PHP 5.4 auf Arrays unterschiedlicher Größe signifikant schneller.

Ich habe ein Testskript für reale Daten erstellt, um json_encode mit serialize und json_decode mit unserialize zu vergleichen. Der Test wurde auf dem Caching-System einer E-Commerce-Site in der Produktion ausgeführt. Es nimmt einfach die Daten, die sich bereits im Cache befinden, und testet die Zeiten, um alle Daten zu codieren / decodieren (oder zu serialisieren / unserialisieren), und ich füge sie in eine übersichtliche Tabelle ein.

Ich habe dies auf einem gemeinsam genutzten PHP 5.4-Hosting-Server ausgeführt.

Die Ergebnisse waren sehr schlüssig, dass für diese großen bis kleinen Datensätze Serialisierung und Unserialisierung die klaren Gewinner waren. Insbesondere für meinen Anwendungsfall sind json_decode und unserialize für das Caching-System am wichtigsten. Unserialize war hier fast ein allgegenwärtiger Gewinner. Es war normalerweise 2 bis 4 Mal (manchmal 6 oder 7 Mal) so schnell wie json_decode.

Es ist interessant, den Unterschied in den Ergebnissen von @ peter-bailey zu bemerken.

Hier ist der PHP-Code, mit dem die Ergebnisse generiert werden:

<?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
quelle
1

Nur zu Ihrer Information: Wenn Sie Ihre Daten zu etwas leicht lesbarem und verständlichem wie JSON serialisieren möchten, das jedoch komprimierter und leistungsfähiger ist, sollten Sie sich das Messagepack ansehen.

Stall
quelle
2
Wenn es nur ein Fyi ist, sollten Sie es besser als Kommentar setzen.
Technophyle
0

JSON ist besser, wenn Sie Daten sichern und auf einem anderen Computer oder über FTP wiederherstellen möchten.

Wenn Sie beispielsweise beim Serialisieren Daten auf einem Windows-Server speichern, über FTP herunterladen und unter einem Linux-Server wiederherstellen, funktioniert dies aufgrund der Neukodierung des Zeichens nicht mehr, da beim Serialisieren die Länge der Zeichenfolgen und im Unicode gespeichert werden > UTF-8-Transcodierung von 1-Byte-Zeichen kann 2 Byte lang werden, wodurch der Algorithmus abstürzt.

Informate.it
quelle
0

THX - für diesen Benchmark-Code:

Meine Ergebnisse für das Array, das ich für die Konfiguration verwende, sind wie folgt: JSON in 0,0031511783599854 Sekunden codiert
PHP in 0,0037961006164551 Sekunden serialisiert
json_encode()war ungefähr 20,47% schneller als serialize() JSON in 0,0070841312408447 Sekunden codiert
PHP in 0,0035839080810547 Sekunden
unserialize()war ungefähr 97,66% schneller alsjson_encode()

Also - testen Sie es an Ihren eigenen Daten.

mk182
quelle
Sie meinen, json_decode () in "unserialize () war ungefähr 97,66% schneller als json_encode ()", ja?
Meezaan-ud-Din
0

Wenn Sie zusammenfassen möchten, was die Leute hier sagen, scheint json_decode / encode schneller zu sein als serialize / unserialize, ABER wenn Sie var_dump ausführen, wird der Typ des serialisierten Objekts geändert. Wenn Sie aus irgendeinem Grund den Typ beibehalten möchten, wählen Sie serialisieren!

(versuchen Sie zum Beispiel stdClass vs Array)

serialisieren / unserialisieren:

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 codieren / decodieren

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]

Wie Sie sehen können, konvertiert json_encode / decode alles in stdClass, was nicht so gut ist, Objektinformationen gehen verloren ... Entscheiden Sie also basierend auf den Anforderungen, insbesondere wenn es sich nicht nur um Arrays handelt ...

David Constantine
quelle
Nur eine Anmerkung: Die meisten anderen Antworten besagen, dass Serialisieren / Unserialisieren schneller ist.
Ecker00
-3

Ich würde Ihnen empfehlen, Super Cache zu verwenden, einen Dateicache-Mechanismus, der json_encodeoder nicht verwendet serialize. Es ist einfach zu bedienen und im Vergleich zu anderen PHP-Cache-Mechanismen sehr schnell.

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

Ex:

<?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
quelle
-1. Obwohl dies eine bessere Lösung sein könnte, beantwortet kein Teil dieser Antwort tatsächlich die Frage des OP. Versuchen Sie in Zukunft vielleicht, die Frage zu beantworten, lassen Sie aber unten einen Vorschlag, dass eine alternative Lösung eine Untersuchung wert sein könnte.
Starbeamrainbowlabs