Bevorzugte Methode zum Speichern von PHP-Arrays (json_encode vs. serialize)
Lesezeit: 10 Minuten
Kyle Farris
Ich muss ein mehrdimensionales assoziatives Array von Daten zu Caching-Zwecken in einer Flatfile speichern. Ich könnte gelegentlich auf die Notwendigkeit stoßen, es für die Verwendung in meiner Webanwendung in JSON zu konvertieren, aber die überwiegende Mehrheit der Zeit werde ich das Array direkt in PHP verwenden.
Wäre es effizienter, das Array als JSON oder als PHP-serialisiertes Array in dieser Textdatei zu speichern? Ich habe mich umgesehen und es scheint, dass in den neuesten Versionen von PHP (5.3) json_decode ist eigentlich schneller als unserialize.
Ich neige derzeit dazu, das Array als JSON zu speichern, da ich das Gefühl habe, 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 so sein schneller zu decodieren (obwohl ich mir nicht sicher bin, was die Codierung betrifft).
Kennt jemand Fallstricke? Hat jemand gute Benchmarks, um die Leistungsvorteile beider Methoden zu zeigen?
Warum nicht einfach so etwas tun: $array = array('foo' => 'bar'); file_put_contents('foo.php', "<?php return ".var_export($array, true) . ";"); . und . $array = file_get_contents('foo.php'))); Natürlich, wenn dies für viel größere Datenmengen ist, würde ich wahrscheinlich mit … CSV gehen. Also vielleicht nicht das sexyste – aber es gibt es aus gutem Grund schon länger als uns beide – und es gibt eine hervorragende Unterstützung in PHP für den teilweisen oder gestreamten Zugriff auf wirklich große Datensätze.
– Christoffer Bubach
30. Juli 2021 um 16:34 Uhr
Peter Bailey
Kommt auf deine Prioritäten an.
Wenn Leistung Ihre absolute Fahreigenschaft ist, dann nehmen Sie auf jeden Fall den Schnellsten. Stellen Sie einfach sicher, dass Sie die Unterschiede vollständig verstanden haben, bevor Sie eine Wahl treffen
nicht wie serialize() Sie müssen 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 nicht aushebeln __sleep() und __wakeup() mit JSON
Standardmäßig werden nur öffentliche Eigenschaften mit JSON serialisiert. (in PHP>=5.4 kannst du umsetzen JsonSerializable um dieses Verhalten zu ändern).
JSON ist portabler
Und es gibt wahrscheinlich noch ein paar andere Unterschiede, die mir im Moment nicht einfallen.
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';
}
“JSON konvertiert UTF-8-Zeichen in Unicode-Escape-Sequenzen.” Nicht mehr unbedingt wahr: Wir haben jetzt JSON_UNESCAPED_UNICODE.
– TRIG
24. November 2012 um 17:01 Uhr
Hier sind wir fast 5 Jahre später und ich habe die Tests erneut durchgeführt (nur die json_encode) und es ist im Durchschnitt etwa 131 % schneller als die Serialisierung jetzt. Es muss also einige ziemlich nette Verbesserungen dieser Funktion in 5.4.x gegenüber 5.3.x geben. Insbesondere führe ich 5.4.24 auf CentOS 6 aus. Also, yay für JSON !!
– Kyle Farris
7. März 2014 um 21:56 Uhr
In meinem Fall codieren wir einmal und decodieren viel, also haben wir json_decode vs. unserialize verglichen und die Ergebnisse waren JSON-dcodiert in 0,06662392616272 Sekunden. PHP deserialisiert in 0,093269109725952 Sekunden.
– Benutzer1642018
28. Juli 2014 um 3:05 Uhr
Interessant: Wenn Sie diesen Code weiter ausführen 3v4l.orglaufen die neuesten PHP7-Entwicklungs-Builds serialize schneller als json_encode: „serialize() war ungefähr 76,53 % schneller als json_encode()“
– marcvangend
9. März 2015 um 12:46 Uhr
2017, PHP 7.1 und serialize() was roughly 35.04% faster than json_encode()
– Elias Soares
25. Oktober 2017 um 17:01 Uhr
JSON ist einfacher und schneller als das Serialisierungsformat von PHP und sollte verwendet werden wenn nicht:
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 als die richtige Klasse deserialisiert werden müssen
Sie interagieren mit alten PHP-Versionen, die json_decode nicht unterstützen
Gute Antwort. Haha, 127 Level tief scheint ein bisschen verrückt zu sein; Zum Glück gehe ich nur wie 2-3 höchstens. Haben Sie Daten, die die Tatsache belegen, dass json_decode/json_encode schneller ist als unserialize/serialize?
– Kyle Farris
29. April 2009 um 20:34 Uhr
Ich habe es vor einiger Zeit getestet und json kam schneller heraus – ich habe die Daten jedoch nicht mehr.
– Greg
29. April 2009 um 21:02 Uhr
„5.3.0 Optionale Tiefe hinzugefügt. Die Standard-Rekursionstiefe wurde von 128 auf 512 erhöht.“
– giorgio79
15. Dezember 2011 um 6:30 Uhr
Ich würde der obigen Liste noch einen Punkt hinzufügen: json_encode() sollte nicht verwendet werden, wenn Ihre Daten möglicherweise ungültige UTF-8-Bytesequenzen enthalten. Für solche Daten gibt es einfach false zurück. Versuchen Sie es zum Beispiel mit: var_dump(json_encode(“\xEF\xEF”));
– pako
20. Mai 2015 um 20:28 Uhr
Es stimmt nicht, dass es im Allgemeinen schneller ist. Wenn Sie ein kleines Array mit etwa 500 Einträgen haben, ist unserialisieren/serialisieren tatsächlich 200-400 % schneller als json_decode/json_encode (PHP 5.6.19).
– Adam
12. August 2016 um 6:51 Uhr
Taco
Zu diesem Thema habe ich einen Blogpost geschrieben: “Ein großes Array zwischenspeichern: JSON, serialisieren oder var_export?“. In diesem Beitrag wird gezeigt, dass die 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.
Der Link ist nicht mehr verfügbar.
– Martin Thoma
28. Februar 2015 um 5:35 Uhr
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.
– Tacos
2. März 2015 um 10:04 Uhr
Ich habe einige Tests durchgeführt und eine einfache Funktion zum Testen erstellt, mit großen Arrays (verwendete Funktion von Peter Bailey für diese). json_encode() handelt von 80 % bis 150 % schneller (es geht dort wirklich auf und ab) als serialize(), mit etwa 300 Iterationen. Aber bei Verwendung der kleineren Arrays (array("teams" => array(1 => array(4 arrays of players), 2 => array(4 arrays of players)))), habe ich getestet mit 750.000 Iterationen u serialize() handelt von 6 % bis 10 % schneller in dem Fall. Meine Funktion nimmt die Durchschnittszeiten für alle Iterationen und vergleicht sie. Ich könnte es hier als eine der Antworten posten
– MiChAeLoKGB
23. Mai 2015 um 23:36 Uhr
wenn die Daten nur von PHP verwendet werden, ist var_export mein Ding. Man muss nur auf mögliche Syntaxfehler im Include-Gedanken achten.
– Gfra54
15. Oktober 2015 um 10:14 Uhr
Blog gibt es nicht mehr
– Popeye
3. Oktober 2018 um 11:50 Uhr
Y hat gerade die serialisierte und json-Codierung und -Decodierung getestet, plus die Größe, die die gespeicherte Zeichenfolge benötigt.
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 kodiert und einen kleineren String ergibt, aber Deserialize ist schneller beim Dekodieren des Strings.
Wie wäre es mit heute? Jetzt, wo wir PHP 7.*.* und sogar PHP 8.*.* haben? Sollten wir igbinary ausprobieren? Danke!
– Tonix
13. Mai 2021 um 5:34 Uhr
Wenn Sie Informationen zwischenspeichern, die Sie letztendlich zu einem späteren Zeitpunkt “einbeziehen” möchten, sollten Sie versuchen, sie zu verwenden var_export. Auf diese Weise nehmen Sie den Treffer nur beim “serialisieren” und nicht beim “unserialisieren”.
Dies ist höchstwahrscheinlich der schnellste Weg, der möglich ist. Ich habe ein Beispiel zum SO “PHP – schnell serialisieren/deserialisieren”: stackoverflow.com/questions/2545455/…
– dave1010
30. Juli 2010 um 8:56 Uhr
Jeff Whiting
Ich habe den Test um die Deserialisierungsleistung 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 zum Codieren, aber langsam zum Decodieren zu sein. Es könnte also von Ihrer Anwendung abhängen und davon, was Sie am meisten erwarten.
Dies ist höchstwahrscheinlich der schnellste Weg, der möglich ist. Ich habe ein Beispiel zum SO “PHP – schnell serialisieren/deserialisieren”: stackoverflow.com/questions/2545455/…
– dave1010
30. Juli 2010 um 8:56 Uhr
Gemeinschaft
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, bei 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, also dachte ich über PHP-Caching-Systeme nach.
Ich habe es versucht apcu aber es entsprach nicht den Anforderungen, der Speicher ist in diesem Fall nicht zuverlässig genug. Der nächste Schritt war das Zwischenspeichern in eine Datei mit Serialisierung.
Die Tabelle hat 14355 Einträge mit 18 Spalten, das sind meine Tests und Statistiken zum Lesen des serialisierten Caches:
JSON:
Wie Sie alle sagten, die größten Unannehmlichkeiten mit json_encode/json_decode ist, dass es alles in ein verwandelt StdClass Instanz (oder Objekt). Wenn Sie es durchlaufen müssen, werden Sie es wahrscheinlich in ein Array umwandeln, und ja, es erhöht die Umwandlungszeit
Das ist besser, erfordert aber eine neue Erweiterung; Kompilieren manchmal ängstliche Menschen …
IgBinär
@GingerDog erwähnt binär. Beachten Sie, dass ich die eingestellt habe igbinary.compact_strings=Offweil ich mich mehr um die Leseleistung als um die Dateigröße kümmere.
Bessere Leistung als JSON, je größer das Array ist, desto langsamer json_decode ist, aber das ist dir schon neu.
Diese externen Erweiterungen schränken die Dateigröße ein 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 wie mit einer Standard-PHP-Funktion?
Wir können auch ableiten, dass Sie je nach Ihren Bedürfnissen etwas anderes wählen als jemand anderes:
IgBinary ist wirklich nett und performt besser als MsgPack
Msgpack komprimiert Ihre Daten besser (beachten Sie, dass ich die Option igbinary compact.string nicht ausprobiert habe).
Sie möchten nicht kompilieren? Standards verwenden.
Das war’s, ein weiterer Vergleich der Serialisierungsmethoden, um Ihnen bei der Auswahl zu helfen!
*Getestet mit PHPUnit 3.7.31, PHP 5.5.10 – nur Dekodierung mit einer Standard-Festplatte und alter Dual-Core-CPU – durchschnittliche Zahlen bei 10 gleichen Anwendungsfalltests, Ihre Statistiken könnten unterschiedlich sein
Warum nicht das Flag an json_decode übergeben, um die Rückgabe von Arrays zu erzwingen?
– Alex Jaroschewitsch
23. November 2014 um 23:51 Uhr
Weil es langsam ist. Ich habe das nicht getestet, aber ich denke, dass es schneller ist, einfach die Typänderung von PHP zu erzwingen.
– Sojuka
24. November 2014 um 20:59 Uhr
Ich weiß nur, dass das Erstellen von Arrays viel schneller ist als Objekte in PHP.
– Alex Jaroschewitsch
25. November 2014 um 6:44 Uhr
Du sprichst also von json_decode($object, true)im Grunde wird es dasselbe tun wie (array) json_decode($object) aber rekursiv wäre das dasselbe Verhalten und es würde in beiden Fällen erhebliche Kosten verursachen. Beachten Sie, dass ich die Leistungsunterschiede zwischen nicht getestet habe StdClass und array aber darum geht es hier eigentlich nicht.
– Sojuka
25. November 2014 um 10:37 Uhr
Ich bin mir sicher, dass es weitere Kosten sind, weil es auf einer niedrigeren Ebene ohne Objekte gemacht wird.
– Alex Jaroschewitsch
26. November 2014 um 15:00 Uhr
9864900cookie-checkBevorzugte Methode zum Speichern von PHP-Arrays (json_encode vs. serialize)yes
Warum nicht einfach so etwas tun:
$array = array('foo' => 'bar'); file_put_contents('foo.php', "<?php return ".var_export($array, true) . ";");
. und .$array = file_get_contents('foo.php')));
Natürlich, wenn dies für viel größere Datenmengen ist, würde ich wahrscheinlich mit … CSV gehen. Also vielleicht nicht das sexyste – aber es gibt es aus gutem Grund schon länger als uns beide – und es gibt eine hervorragende Unterstützung in PHP für den teilweisen oder gestreamten Zugriff auf wirklich große Datensätze.– Christoffer Bubach
30. Juli 2021 um 16:34 Uhr