Metodo preferito per archiviare array PHP (json_encode vs serialize)


608

Devo archiviare un array associativo multidimensionale di dati in un file flat ai fini della memorizzazione nella cache. Occasionalmente potrei incontrare la necessità di convertirlo in JSON per l'uso nella mia app Web, ma la maggior parte delle volte userò l'array direttamente in PHP.

Sarebbe più efficiente archiviare l'array come JSON o come array serializzato PHP in questo file di testo? Mi sono guardato intorno e sembra che nelle ultime versioni di PHP (5.3), json_decodesia effettivamente più veloce di unserialize.

Attualmente mi sto orientando verso l'archiviazione dell'array come JSON poiché ritengo che sia più facile da leggere da un essere umano se necessario, può essere utilizzato sia in PHP che in JavaScript con il minimo sforzo, e da quello che ho letto, potrebbe anche essere più veloce da decodificare (non sono sicuro della codifica, però).

Qualcuno sa di eventuali insidie? Qualcuno ha buoni parametri di riferimento per mostrare i vantaggi in termini di prestazioni di entrambi i metodi?

Risposte:


563

Dipende dalle tue priorità.

Se la prestazione è la tua caratteristica di guida assoluta, allora usa quella più veloce. Assicurati di avere una piena comprensione delle differenze prima di fare una scelta

  • Diversamente serialize()è necessario aggiungere un parametro aggiuntivo per mantenere intatti i caratteri UTF-8: json_encode($array, JSON_UNESCAPED_UNICODE) (altrimenti converte i caratteri UTF-8 in sequenze di escape Unicode).
  • JSON non avrà memoria di quale fosse la classe originale dell'oggetto (vengono sempre ripristinati come istanze di stdClass).
  • Non puoi sfruttare __sleep()e __wakeup()con JSON
  • Per impostazione predefinita, solo le proprietà pubbliche sono serializzate con JSON. (in PHP>=5.4te puoi implementare JsonSerializable per cambiare questo comportamento).
  • JSON è più portatile

E probabilmente ci sono alcune altre differenze che non riesco a pensare al momento.

Un semplice test di velocità per confrontare i due

<?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 converte i caratteri UTF-8 in sequenze di escape unicode." Non è più necessariamente vero: ora abbiamo JSON_UNESCAPED_UNICODE.
TRiG

32
Qui siamo quasi 5 anni dopo e ho eseguito di nuovo i test (solo il json_encode) e ora è in media circa il 131% più veloce rispetto alla serializzazione ora. Quindi, ci devono essere alcuni miglioramenti piuttosto carini a quella funzione in 5.4.x rispetto a 5.3.x. In particolare, sto eseguendo 5.4.24 su CentOS 6. Quindi, yay per JSON !!
KyleFarris

8
nel mio caso abbiamo codificato una volta e decodificato molto, quindi abbiamo confrontato json_decode vs unserialize e i risultati sono stati codificati JSON in 0,06662392616272 secondi <br> PHP non serializzato in 0,093269109725952 secondi <br> json_decode () era circa 39,99% più veloce di unserialize ()
AMB,

21
Interessante: se esegui questo codice su 3v4l.org , le ultime build di sviluppo PHP7 vengono serializzate più velocemente di json_encode: "serialize () era circa il 76,53% più veloce di json_encode ()"
marcvangend

21
2017, PHP 7.1 eserialize() was roughly 35.04% faster than json_encode()
Elias Soares,

239

JSON è più semplice e veloce del formato di serializzazione di PHP e dovrebbe essere utilizzato a meno che :

  • Stai memorizzando array profondamente annidati json_decode():: "Questa funzione restituirà false se i dati codificati JSON sono più profondi di 127 elementi."
  • Stai memorizzando oggetti che devono essere non serializzati come la classe corretta
  • Stai interagendo con vecchie versioni di PHP che non supportano json_decode

12
Bella risposta. Haha, 127 livelli di profondità sembra un po 'folle; per fortuna vado solo al massimo 2-3. Hai dei dati a sostegno del fatto che json_decode / json_encode è più veloce di non serializzare / serializzare?
KyleFarris,

1
L'ho provato un po 'di tempo fa e Json è uscito più velocemente, ma non ho più i dati.
Greg,

47
"5.3.0 Aggiunta la profondità opzionale. La profondità di ricorsione predefinita è stata aumentata da 128 a 512"
giorgio79,

4
Vorrei aggiungere un altro elemento all'elenco sopra: json_encode () non dovrebbe essere usato se i tuoi dati potrebbero contenere sequenze di byte UTF-8 non valide. Restituisce semplicemente falso per tali dati. Prova ad esempio: var_dump (json_encode ("\ xEF \ xEF"));
pako,

2
Non è vero che è più veloce in generale. Se hai un piccolo array con circa ~ 500 voci, allora la serializzazione / serializzazione è in realtà del 200-400% più veloce di json_decode / json_encode (PHP 5.6.19)
Adam

59

Ho scritto un post sul blog su questo argomento: " Cache un array di grandi dimensioni: JSON, serializzare o var_export? " . In questo post viene mostrato che serializzare è la scelta migliore per array di piccole e grandi dimensioni. Per array molto grandi (> 70 MB) JSON è la scelta migliore.


8
Il link non è più disponibile.
Martin Thoma,

1
Grazie, alce, ho aggiornato il link. Sebbene l'articolo abbia quasi 6 anni e potrebbe non essere così preciso per le attuali versioni di PHP.
Taco

Ho fatto alcuni test e fatto una semplice funzione per testarlo, con grandi array (funzione usata da Peter Bailey per quelli) json_encode()è circa l' 80% al 150% più veloce (va davvero su e giù lì) rispetto a serialize(), con circa 300 iterazioni. Ma quando array("teams" => array(1 => array(4 arrays of players), 2 => array(4 arrays of players)))ho usato le matrici più piccole ( ), ho fatto un test con 750.000 iterazioni e in quel caso è più veloce del 6-10%serialize() circa . La mia funzione prende i tempi medi per tutte le iterazioni e le confronta. Potrei pubblicarlo qui come una delle risposte
MiChAeLoKGB

se i dati sono usati solo da PHP, var_export è la mia cosa. Devo solo stare attento con possibili errori di sintassi nel pensiero incluso.
Gfra54,

3
il blog non esiste più
popeye,

53

Potresti anche essere interessato a https://github.com/phadej/igbinary - che fornisce un 'motore' di serializzazione diverso per PHP.

Le mie cifre "prestazionali" casuali / arbitrarie, usando PHP 5.3.5 su una piattaforma a 64 bit mostrano:

JSON:

  • JSON codificato in 2.180496931076 secondi
  • JSON decodificato in 9.8368630409241 secondi
  • dimensione "String" serializzata: 13993

PHP nativo:

  • PHP serializzato in 2.9125759601593 secondi
  • PHP non serializzato in 6.4348418712616 secondi
  • dimensione "String" serializzata: 20769

Igbinary:

  • WIN igbinary serializzato in 1.6099879741669 secondi
  • WIN igbinrary non serializzato in 4.7737920284271 secondi
  • Dimensione "String" serializzata WIN : 4467

Quindi, igbinary_serialize () e igbinary_unserialize () è più veloce e utilizza meno spazio su disco.

Ho usato il codice fillArray (0, 3) come sopra, ma ho allungato le stringhe delle chiavi dell'array.

igbinary può memorizzare gli stessi tipi di dati della serializzazione nativa di PHP (quindi nessun problema con oggetti ecc.) e puoi dire a PHP5.3 di usarlo per la gestione della sessione, se lo desideri.

Vedi anche http://ilia.ws/files/zendcon_2010_hidden_features.pdf - in particolare diapositive 14/15/16


25

Y ha appena testato la codifica e decodifica serializzata e json, oltre alle dimensioni che prenderà la stringa memorizzata.

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

Possiamo concludere che JSON codifica più velocemente e produce una stringa più piccola, ma annullare la serializzazione è più veloce per decodificare la stringa.


6
Non so perché le persone eseguano sempre test delle prestazioni con un set di dati così piccolo. In questo modo hai tutto il sovraccarico che aggiunge errori ai risultati. E se le persone sono interessate alle prestazioni, è probabilmente perché hanno un set di dati molto grande, perché non ha senso guadagnare un micro sec una volta.
Yann Sagon,

1
Molto spesso eseguo l'iterazione su molti piccoli set di dati. Con centinaia di piccoli set di dati, guadagnare 1mS per ognuno è ancora interessante.
Teson,

@YannSagon Anche con piccoli set di dati ha senso eseguire un test delle prestazioni. Come dovresti sapere prima del test se si tratta solo di un micro secondo?
Adamo,

17

Se stai memorizzando nella cache informazioni che alla fine vorresti "includere" in un secondo momento, potresti provare a usare var_export . In questo modo prendi il colpo solo nella "serializzazione" e non nella "non serializzazione".


Questo è probabilmente il modo più veloce possibile. Ho scritto un esempio sul SO "PHP - veloce serializzare / unserialize": stackoverflow.com/questions/2545455/...
dave1010

12

Ho aumentato il test per includere le prestazioni di serializzazione. Ecco i numeri che ho ricevuto.

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

Quindi json sembra essere più veloce per la codifica ma lento nella decodifica. Quindi potrebbe dipendere dalla tua applicazione e da cosa ti aspetti di fare di più.


9

Argomento davvero carino e dopo aver letto le poche risposte, voglio condividere i miei esperimenti sull'argomento.

Ho un caso d'uso in cui è necessario interrogare una tabella "enorme" quasi ogni volta che parlo con il database (non chiedo perché, solo un dato di fatto). Il sistema di cache del database non è appropriato in quanto non memorizzerà nella cache le diverse richieste, quindi ho pensato ai sistemi di cache php.

Ho provato apcuma non si adattava alle esigenze, la memoria non è abbastanza affidabile in questo caso. Il passo successivo è stato quello di memorizzare nella cache un file con serializzazione.

La tabella ha 14355 voci con 18 colonne, questi sono i miei test e le statistiche sulla lettura della cache serializzata:

JSON:

Come hai detto, l'inconveniente maggiore di json_encode/ json_decodeè che trasforma tutto in StdClassun'istanza (o Oggetto). Se è necessario eseguirne il loop, trasformarlo in un array è ciò che probabilmente si farà e, sì, sta aumentando il tempo di trasformazione

tempo medio: 780,2 ms; uso della memoria: 41,5 MB; dimensione del file cache: 3,8 MB

Msgpack

@hutch menziona msgpack . Sito Web grazioso. Facciamo una prova, vero?

tempo medio: 497 ms; uso della memoria: 32 MB; dimensione del file cache: 2,8 MB

Va meglio, ma richiede una nuova estensione; compilare persone a volte spaventate ...

IgBinary

@GingerDog menziona igbinary . Si noti che ho impostato il igbinary.compact_strings=Offperché mi interessa di più leggere le prestazioni piuttosto che le dimensioni del file.

tempo medio: 411,4 ms; uso della memoria: 36,75 MB; dimensione del file cache: 3,3 MB

Meglio del pacchetto msg. Tuttavia, anche questo richiede la compilazione.

serialize/unserialize

tempo medio: 477,2 ms; uso della memoria: 36,25 MB; dimensione del file cache: 5,9 MB

Prestazioni migliori rispetto a JSON, più grande è l'array, più lento json_decodeè, ma lo sai già.

Quelle estensioni esterne stanno restringendo le dimensioni del file e sembrano grandi sulla carta. I numeri non mentono *. A che serve compilare un'estensione se si ottengono quasi gli stessi risultati che si otterrebbero con una funzione PHP standard?

Possiamo anche dedurre che, in base alle tue esigenze, sceglierai qualcosa di diverso rispetto a qualcun altro:

  • IgBinary è davvero bello e funziona meglio di MsgPack
  • Msgpack è meglio nel comprimere i tuoi dati (nota che non ho provato l'opzione igbinary compact.string).
  • Non vuoi compilare? Usa gli standard.

Ecco, un altro confronto tra i metodi di serializzazione per aiutarti a scegliere quello!

* Testato con PHPUnit 3.7.31, php 5.5.10 - solo decodifica con hard disk standard e vecchia CPU dual core - numeri medi su 10 test dello stesso caso d'uso, le tue statistiche potrebbero essere diverse


Perché non passare la bandiera a json_decode per forzare le matrici di ritorno?
Alex Yaroshevich,

Perché è lento. Non l'ho provato ma penso che forzare il cambio di tipo da php sia più veloce.
soyuka,

So solo che la creazione di array è molto più veloce degli oggetti in php.
Alex Yaroshevich,

Quindi stai parlando json_decode($object, true), fondamentalmente farà lo stesso (array) json_decode($object)ma in modo ricorsivo, quindi sarebbe lo stesso comportamento e avrà un costo significativo in entrambi i casi. Si noti che non ho testato differenze di prestazioni tra StdClasse, arrayma non è proprio questo il punto.
soyuka,

Sono sicuro che è un altro costo perché è fatto a livello inferiore senza oggetti.
Alex Yaroshevich,

8

Sembra che serializzare sia quello che userò per 2 motivi:

  • Qualcuno ha sottolineato che unserialize è più veloce di json_decode e un caso "read" sembra più probabile di un caso "write".

  • Ho avuto problemi con json_encode quando ho stringhe con caratteri UTF-8 non validi. Quando ciò accade, la stringa finisce per essere vuota causando la perdita di informazioni.


puoi per favore elaborare il tuo ultimo punto con un esempio
Naveen Saroye,

6

L'ho testato in modo molto approfondito su un multi-hash nidificato abbastanza complesso, leggermente annidato con tutti i tipi di dati (stringa, NULL, numeri interi) e serializzare / non serializzare è finito molto più velocemente di json_encode / json_decode.

L'unico vantaggio che Json ha nei miei test è stato la sua dimensione "imballata" più piccola.

Questi sono fatti in PHP 5.3.3, fammi sapere se vuoi maggiori dettagli.

Ecco i risultati dei test, quindi il codice per produrli. Non posso fornire i dati del test poiché rivelerebbero informazioni che non posso lasciare uscire allo stato brado.

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!';
}

Ho appena eseguito un test simile con PHP 5.4.12 e ho trovato risultati simili: {un,} serializzare è più veloce. I miei dati sono hash nidificati a 3 livelli di profondità (900k serializzati).
sorpigal

6

Ho fatto anche un piccolo benchmark. I miei risultati sono stati gli stessi. Ma ho bisogno delle prestazioni di decodifica. Dove ho notato, come hanno detto anche alcune persone sopra, unserializeè più veloce di json_decode. unserializerichiede circa il 60-70% delle json_decodevolte. Quindi la conclusione è abbastanza semplice: quando hai bisogno di prestazioni nella codifica, usa json_encode, quando hai bisogno di prestazioni durante la decodifica, usa unserialize. Poiché non è possibile unire le due funzioni, è necessario effettuare una scelta in cui sono necessarie maggiori prestazioni.

Il mio punto di riferimento in pseudo:

  • Definisci l'array $ arr con alcune chiavi e valori casuali
  • per x <100; x ++; serializzare e json_encode un array_rand di $ arr
  • per y <1000; y ++; json_decode la stringa codificata json - tempo di calc
  • per y <1000; y ++; annullare la serializzazione della stringa serializzata - tempo di calc
  • echo il risultato che è stato più veloce

Su avarage: unserialize ha vinto 96 volte su 4 volte il json_decode. Con una media di circa 1,5 ms oltre 2,5 ms.


3

Prima di prendere la decisione finale, tenere presente che il formato JSON non è sicuro per gli array associativi, json_decode()ma li restituirà come oggetti:

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

L'output è:

Array
(
    [Frodo] => hobbit
    [Gimli] => dwarf
    [Gandalf] => wizard
)
stdClass Object
(
    [Frodo] => hobbit
    [Gimli] => dwarf
    [Gandalf] => wizard
)

Anzi, hai ragione. Voglio dire, è Javascript oggetto notazione dopotutto! Per fortuna, se sai che quello che hai codificato usando json_encodeera un array associativo, puoi facilmente forzarlo a tornare in un array in questo modo: $json = json_encode($some_assoc_array); $back_to_array = (array)json_decode($json);Inoltre, è bene notare che puoi accedere agli oggetti allo stesso modo degli array in PHP, quindi in uno scenario tipico, non si saprebbe nemmeno la differenza. Un buon punto però!
KyleFarris,

30
@toomuchphp, scusa ma ti sbagli. Esiste un secondo parametro per json_decode 'bool $ assoc = false' che consente a json_decode di produrre un array. @KyleFarris, anche questo dovrebbe essere più veloce dell'uso del typecast per l'array.
Janpio,

la risposta non è corretta. quando si utilizza true come secondo parametro della funzione, json_decode () restituirà array associativi anziché oggetti.
Marvin Saldinger,

3

In primo luogo, ho modificato lo script per fare un po 'più di benchmarking (e anche fare 1000 esecuzioni anziché solo 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';
}

Ho usato questa build di PHP 7:

PHP 7.0.14 (cli) (costruito: 18 gennaio 2017 19:13:23) (NTS) Copyright (c) 1997-2016 The PHP Group Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies con Zend OPcache v7.0.14, Copyright (c) 1999-2016, di Zend Technologies

E i miei risultati sono stati:

serialize () (vittorie: 999) era circa il 10,98% più veloce di json_encode () unserialize () (vittorie: 987) era circa il 33,26% più veloce di json_decode () unserialize () (vittorie: 987) era circa il 48,35% più veloce dell'array json_decode ()

Quindi chiaramente , serializzare / unserialize è il metodo più veloce , mentre json_encode / decode è il più portatile.

Se si considera uno scenario in cui si leggono / scrivono dati serializzati 10 volte o più spesso di quanto sia necessario inviare o ricevere da un sistema non PHP, è ANCORA meglio utilizzare serializzare / annullare la serializzazione e averlo json_encode o json_decode prima della serializzazione in termini di tempo.


2

Dai un'occhiata ai risultati qui (scusa per l'hacking che mette il codice PHP nella casella del codice JS):

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

RISULTATI: serialize()e unserialize()sono entrambi significativamente più veloci in PHP 5.4 su array di dimensioni variabili.

Ho realizzato uno script di test sui dati del mondo reale per confrontare json_encode vs serialize e json_decode vs unserialize. Il test è stato eseguito sul sistema di memorizzazione nella cache di un sito di e-commerce in produzione. Prende semplicemente i dati già nella cache e verifica i tempi per codificare / decodificare (o serializzare / annullare la serializzazione) di tutti i dati e li inserisco in una tabella facile da vedere.

Ho eseguito questo sul server di hosting condiviso PHP 5.4.

I risultati sono stati molto conclusivi che per questi insiemi di dati da grandi a piccoli serializzare e non serializzare sono stati i vincitori chiari. In particolare per il mio caso d'uso, json_decode e unserialize sono i più importanti per il sistema di memorizzazione nella cache. Unserialize è stato quasi un vincitore onnipresente qui. In genere era da 2 a 4 volte (a volte 6 o 7 volte) più veloce di json_decode.

È interessante notare la differenza nei risultati di @ peter-bailey.

Ecco il codice PHP utilizzato per generare i risultati:

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

solo un problema - se vuoi serializzare i tuoi dati su qualcosa di facile da leggere e comprendere come JSON, ma con una maggiore compressione e prestazioni più elevate, dovresti dare un'occhiata a messagepack.


2
se è solo un problema, è meglio metterlo come commento.
tecnophyle

0

JSON è migliore se si desidera eseguire il backup dei dati e ripristinarli su un altro computer o tramite FTP.

Ad esempio con serializzare se si memorizzano i dati su un server Windows, scaricarli via FTP e ripristinarli su uno Linux non potrebbe più funzionare a causa della ricodifica del carattere, poiché serializzare memorizza la lunghezza delle stringhe e in Unicode > La transcodifica UTF-8 di circa 1 byte di caratteri potrebbe diventare lunga 2 byte causando il crash dell'algoritmo.


0

THX - per questo codice di riferimento:

I miei risultati sull'array che utilizzo per la configurazione sono i seguenti: JSON codificato in 0,0031511783599854 secondi
PHP serializzato in 0,0037961006164551 secondi
json_encode()era circa il 20,47% più veloce di serialize() JSON codificato in 0,0070841312408447 secondi
PHP serializzato in 0,0035839080810547 secondi
unserialize()era circa il 97,66% più veloce dijson_encode()

Quindi - testalo sui tuoi dati.


Vuoi dire che json_decode () in "unserialize () era circa il 97,66% più veloce di json_encode ()", sì?
Meezaan-ud-Din,

0

Se per riassumere ciò che la gente dice qui, json_decode / encode sembra più veloce di serializzare / annullare la serializzazione MA se si fa var_dump il tipo di oggetto serializzato viene modificato. Se per qualche motivo vuoi mantenere il tipo, vai con serializza!

(prova ad esempio stdClass vs array)

serialize / unserialize:

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 codifica / decodifica

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]

Come puoi vedere json_encode / decode converte tutto in stdClass, che non è così buono, informazioni sugli oggetti persi ... Quindi decidi in base alle esigenze, soprattutto se non sono solo array ...


Solo una nota: la maggior parte delle altre risposte afferma che serializzare / annullare la serializzazione è più veloce.
Ecker00,

-3

Ti suggerirei di usare Super Cache, che è un meccanismo di cache dei file che non utilizzerà json_encode oserialize . È semplice da usare e molto veloce rispetto ad altri meccanismi di cache PHP.

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

-1. Sebbene possa essere una soluzione migliore, nessuna parte di questa risposta risponde effettivamente alla domanda del PO. In futuro, forse prova a rispondere alla domanda, ma lasciando in fondo un suggerimento che potrebbe valere la pena investigare su una soluzione alternativa.
Starbeamrainbowlabs
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.