Método preferido para almacenar matrices PHP (json_encode vs serialize)

608

Necesito almacenar una matriz asociativa multidimensional de datos en un archivo plano para fines de almacenamiento en caché. De vez en cuando podría encontrar la necesidad de convertirlo a JSON para usarlo en mi aplicación web, pero la gran mayoría de las veces usaré la matriz directamente en PHP.

¿Sería más eficiente almacenar la matriz como JSON o como una matriz serializada PHP en este archivo de texto? He mirado alrededor y parece que en las versiones más recientes de PHP (5.3), en json_decoderealidad es más rápido que unserialize.

Actualmente me estoy inclinando hacia el almacenamiento de la matriz como JSON, ya que siento que es más fácil de leer por un humano si es necesario, puede usarse tanto en PHP como en JavaScript con muy poco esfuerzo, y por lo que he leído, incluso podría ser más rápido de decodificar (sin embargo, no estoy seguro acerca de la codificación).

¿Alguien sabe de alguna trampa? ¿Alguien tiene buenos puntos de referencia para mostrar los beneficios de rendimiento de cualquiera de los métodos?

KyleFarris
fuente

Respuestas:

563

Depende de tus prioridades.

Si el rendimiento es su característica de conducción absoluta, entonces utilice la más rápida. Solo asegúrese de comprender completamente las diferencias antes de tomar una decisión

  • A diferencia de esto serialize(), debe agregar un parámetro adicional para mantener intactos los caracteres UTF-8: json_encode($array, JSON_UNESCAPED_UNICODE) (de lo contrario, convierte los caracteres UTF-8 en secuencias de escape Unicode).
  • JSON no tendrá memoria de cuál era la clase original del objeto (siempre se restauran como instancias de stdClass).
  • No puede aprovechar __sleep()y __wakeup()con JSON
  • De forma predeterminada, solo las propiedades públicas se serializan con JSON. (en PHP>=5.4usted puede implementar JsonSerializable para cambiar este comportamiento).
  • JSON es más portátil

Y probablemente hay algunas otras diferencias que no puedo pensar en este momento.

Una prueba de velocidad simple para comparar los dos

<?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
fuente
31
"JSON convierte los caracteres UTF-8 en secuencias de escape unicode". Ya no es necesariamente cierto: ahora tenemos JSON_UNESCAPED_UNICODE.
TRiG
32
Aquí estamos casi 5 años después y realicé las pruebas nuevamente (solo el json_encode) y está promediando aproximadamente un 131% más rápido que la serialización ahora. Entonces, debe haber algunas mejoras bastante buenas para esa función en 5.4.x sobre 5.3.x. Específicamente, estoy ejecutando 5.4.24 en CentOS 6. Entonces, ¡yay para JSON!
KyleFarris
8
en mi caso codificamos una vez y decodificamos mucho, así que comparamos el json_decode vs unserialize y los resultados fueron codificados en JSON en 0.06662392616272 segundos <br> PHP no serializado en 0.093269109725952 segundos <br> json_decode () fue aproximadamente 39.99% más rápido que unserialize ()
AMB
21
Interesante: si ejecuta este código en 3v4l.org , las últimas compilaciones de desarrollo de PHP7 ejecutan serializar más rápido que json_encode: "serialize () fue aproximadamente 76.53% más rápido que json_encode ()"
marcvangend 9/15
21
2017, PHP 7.1 yserialize() was roughly 35.04% faster than json_encode()
Elias Soares
239

JSON es más simple y rápido que el formato de serialización de PHP y debe usarse a menos que :

  • Está almacenando matrices profundamente anidadas json_decode():: "Esta función devolverá falso si los datos codificados con JSON son más profundos que 127 elementos".
  • Está almacenando objetos que no deben ser serializados como la clase correcta
  • Estás interactuando con versiones antiguas de PHP que no admiten json_decode
Greg
fuente
12
Gran respuesta. Jaja, 127 niveles de profundidad parece un poco loco; afortunadamente solo voy como 2-3 como máximo. ¿Tiene algún dato para respaldar el hecho de que json_decode / json_encode es más rápido que unserialize / serialize?
KyleFarris
1
Lo probé hace un tiempo y json salió más rápido, aunque ya no tengo los datos.
Greg
47
"5.3.0 Se agregó la profundidad opcional. La profundidad de recursión predeterminada se incrementó de 128 a 512"
giorgio79
44
Agregaría un elemento más a la lista anterior: json_encode () no debe usarse si sus datos pueden contener secuencias de bytes UTF-8 no válidas. Simplemente devuelve falso para dichos datos. Pruebe por ejemplo: var_dump (json_encode ("\ xEF \ xEF"));
pako
2
No es cierto que sea más rápido en general. Si tiene una matriz pequeña con aproximadamente ~ 500 entradas, entonces la deserialización / serialización es en realidad 200-400% más rápida que json_decode / json_encode (PHP 5.6.19)
Adam
59

He escrito una entrada de blog sobre este tema: " Caché una gran matriz: JSON, serializar o var_export? " . En esta publicación se muestra que serializar es la mejor opción para arreglos de tamaño pequeño a grande. Para matrices muy grandes (> 70 MB), JSON es la mejor opción.

Taco
fuente
8
El enlace ya no está disponible.
Martin Thoma
1
Gracias, alce, he actualizado el enlace. Aunque el artículo tiene casi 6 años y podría no ser tan preciso para las versiones actuales de PHP.
Taco
Hice algunas pruebas e hice una función simple para probarlo, con grandes matrices (función utilizada de Peter Bailey para esos) json_encode()es aproximadamente 80% a 150% más rápido (realmente va arriba y abajo) que serialize(), con aproximadamente 300 iteraciones. Pero cuando utilicé las matrices más pequeñas ( array("teams" => array(1 => array(4 arrays of players), 2 => array(4 arrays of players)))), probé con 750,000 iteraciones y en ese caso serialize()es aproximadamente 6% a 10% más rápido. Mi función toma los tiempos promedio para todas las iteraciones y los compara. Podría publicarlo aquí como una de las respuestas
MiChAeLoKGB
si PHP solo usa los datos, var_export es lo mío. Solo debe tener cuidado con los posibles errores de sintaxis en el pensamiento de inclusión.
Gfra54
3
blog ya no existe
popeye
53

También puede estar interesado en https://github.com/phadej/igbinary , que proporciona un 'motor' de serialización diferente para PHP.

Mis cifras de 'rendimiento' aleatorias / arbitrarias, usando PHP 5.3.5 en una plataforma de 64 bits muestran:

JSON

  • JSON codificado en 2.180496931076 segundos
  • JSON decodificado en 9.8368630409241 segundos
  • tamaño serializado de "Cadena": 13993

PHP nativo:

  • PHP serializado en 2.9125759601593 segundos
  • PHP no serializado en 6.4348418712616 segundos
  • tamaño serializado de "Cadena": 20769

Igbinary:

  • WIN igbinary serializado en 1.6099879741669 segundos
  • WIN igbinrary no serializado en 4.7737920284271 segundos
  • WIN serializado "String" Tamaño: 4467

Por lo tanto, es más rápido igbinary_serialize () e igbinary_unserialize () y usa menos espacio en disco.

Utilicé el código fillArray (0, 3) como el anterior, pero hice que las teclas de matriz sean cadenas más largas.

igbinary puede almacenar los mismos tipos de datos que la serialización nativa de PHP (así que no hay problema con los objetos, etc.) y puede decirle a PHP5.3 que lo use para el manejo de la sesión si así lo desea.

Ver también http://ilia.ws/files/zendcon_2010_hidden_features.pdf - específicamente diapositivas 14/15/16

David Goodwin
fuente
25

Y acaba de probar la codificación y decodificación serializada y json, más el tamaño que tomará la cadena almacenada.

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

Podemos concluir que JSON codifica más rápido y da como resultado una cadena más pequeña, pero deserializar es más rápido para decodificar la cadena.

Blunk
fuente
66
No sé por qué la gente siempre hace pruebas de rendimiento con un conjunto de datos tan pequeño. Al hacerlo, tiene todos los gastos generales que agregan errores a sus resultados. Y si las personas están interesadas en el rendimiento, probablemente sea porque tienen un conjunto de datos muy grande, porque no tiene sentido ganar un microsegundo una vez.
Yann Sagon
1
Muy a menudo itero sobre muchos conjuntos de datos pequeños. Con cientos de pequeños conjuntos de datos, aún es interesante obtener 1 ms para cada uno.
Teson
@YannSagon Incluso con pequeños conjuntos de datos, tiene sentido hacer una prueba de rendimiento. ¿Cómo debe saber antes de la prueba si solo se trata de un microsegundo?
Adam
17

Si está almacenando información en caché que finalmente desea "incluir" en un momento posterior, puede intentar usar var_export . De esa forma, solo recibirás el golpe en "serializar" y no en "no serializar".

Jordan S. Jones
fuente
Esta es probablemente la forma más rápida posible. Escribí un ejemplo en el SO "PHP - serialización / deserialización rápida ": stackoverflow.com/questions/2545455/…
dave1010
12

Aumenté la prueba para incluir el rendimiento de deserialización. Aquí están los números que obtuve.

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

Entonces, json parece ser más rápido para la codificación pero lento en la decodificación. Por lo tanto, podría depender de su aplicación y de lo que espera hacer más.

Jeff Whiting
fuente
9

Muy buen tema y después de leer las pocas respuestas, quiero compartir mis experimentos sobre el tema.

Obtuve un caso de uso en el que se debe consultar una tabla "enorme" casi cada vez que hablo con la base de datos (no pregunte por qué, solo un hecho). El sistema de almacenamiento en caché de la base de datos no es apropiado ya que no almacenará en caché las diferentes solicitudes, así que pensé en los sistemas de almacenamiento en caché de php.

Lo intenté apcupero no se ajustaba a las necesidades, la memoria no es lo suficientemente confiable en este caso. El siguiente paso fue almacenar en caché un archivo con serialización.

La tabla tiene 14355 entradas con 18 columnas, esas son mis pruebas y estadísticas sobre la lectura del caché serializado:

JSON

Como todos dijeron, el mayor inconveniente con json_encode/ json_decodees que transforma todo en una StdClassinstancia (u Objeto). Si necesita hacer un bucle, lo que probablemente hará es transformarlo en una matriz, y sí, aumenta el tiempo de transformación

tiempo promedio: 780.2 ms; uso de memoria: 41.5MB; tamaño del archivo de caché: 3.8MB

Msgpack

@hutch menciona msgpack . Bonito sitio web. Vamos a intentarlo, ¿de acuerdo?

tiempo medio: 497 ms; uso de memoria: 32 MB; tamaño del archivo de caché: 2.8MB

Eso es mejor, pero requiere una nueva extensión; compilando a veces personas asustadas ...

IgBinary

@GingerDog menciona igbinary . Tenga en cuenta que lo configuré igbinary.compact_strings=Offporque me importa más leer interpretaciones que el tamaño de archivo.

tiempo promedio: 411.4 ms; uso de memoria: 36.75MB; tamaño del archivo de caché: 3.3MB

Mejor que el paquete de mensajes. Aún así, este también requiere compilación.

serialize/ /unserialize

tiempo medio: 477,2 ms; uso de memoria: 36.25MB; tamaño del archivo de caché: 5.9MB

Mejores rendimientos que JSON, cuanto más grande es la matriz, más lento json_decode es, pero eso ya lo sabes.

Esas extensiones externas están reduciendo el tamaño del archivo y parece genial en papel. Los números no mienten *. ¿Cuál es el punto de compilar una extensión si obtienes casi los mismos resultados que tendrías con una función PHP estándar?

También podemos deducir que, según sus necesidades, elegirá algo diferente a otra persona:

  • IgBinary es realmente agradable y funciona mejor que MsgPack
  • Msgpack es mejor para comprimir sus datos (tenga en cuenta que no probé la opción igbinary compact.string).
  • ¿No quieres compilar? Utiliza estándares.

¡Eso es todo, otra comparación de métodos de serialización para ayudarlo a elegir uno!

* Probado con PHPUnit 3.7.31, php 5.5.10: solo decodificación con un disco duro estándar y una CPU de doble núcleo antigua: números promedio en 10 pruebas de casos de uso iguales, sus estadísticas pueden ser diferentes

soyuka
fuente
¿Por qué no pasar la bandera a json_decode para forzar la devolución de matrices?
Alex Yaroshevich
Porque es lento No probé esto, pero creo que simplemente forzar el cambio de tipo de php es más rápido.
soyuka
Solo sé que crear matrices mucho más rápido que los objetos en php.
Alex Yaroshevich
De lo que estás hablando json_decode($object, true), básicamente hará lo mismo (array) json_decode($object)pero de manera recursiva, de modo que sería el mismo comportamiento y tendría un costo significativo en ambos casos. Tenga en cuenta que no he probado las diferencias de rendimiento entre StdClassy, arraypero ese no es realmente el punto aquí.
soyuka
Estoy seguro de que es otro costo porque se realiza en el nivel inferior sin objetos.
Alex Yaroshevich
8

Parece que serializar es el que voy a usar por 2 razones:

  • Alguien señaló que unserialize es más rápido que json_decode y un caso de 'lectura' suena más probable que un caso de 'escritura'.

  • He tenido problemas con json_encode cuando tengo cadenas con caracteres UTF-8 no válidos. Cuando eso sucede, la cadena termina vacía y causa pérdida de información.

urraka
fuente
Puede por favor elaborar su último punto con un ejemplo
Naveen Saroye
6

He probado esto muy a fondo en un hash múltiple bastante complejo y ligeramente anidado con todo tipo de datos (cadena, NULL, enteros), y serializar / deserializar terminó mucho más rápido que json_encode / json_decode.

La única ventaja que json tiene en mis pruebas es que es un tamaño 'empaquetado' más pequeño.

Estos se realizan en PHP 5.3.3, avíseme si desea más detalles.

Aquí están los resultados de las pruebas y luego el código para producirlos. No puedo proporcionar los datos de la prueba ya que revelaría información que no puedo dejar salir en la naturaleza.

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!';
}
Señor sox
fuente
Acabo de realizar una prueba similar con PHP 5.4.12 y encontré resultados similares: {un,} serializar es más rápido. Mis datos son hashes anidados 3 niveles de profundidad (900k serializados).
sorigal
6

También hice un pequeño punto de referencia. Mis resultados fueron los mismos. Pero necesito el rendimiento de decodificación. Donde me di cuenta, como algunas personas arriba mencionadas también, unserializees más rápido que json_decode. unserializetoma aproximadamente el 60-70% del json_decodetiempo. Entonces, la conclusión es bastante simple: cuando necesite rendimiento en la codificación, use json_encode, cuando necesite rendimiento en la decodificación, useunserialize . Debido a que no puede fusionar las dos funciones, debe elegir dónde necesita más rendimiento.

Mi punto de referencia en pseudo:

  • Defina la matriz $ arr con algunas claves y valores aleatorios
  • para x <100; x ++; serializar y json_encode un array_rand de $ arr
  • para y <1000; y ++; json_decode la cadena codificada json - tiempo de cálculo
  • para y <1000; y ++; deserializar la cadena serializada - tiempo de cálculo
  • hacer eco del resultado que fue más rápido

En promedio: unserialize ganó 96 veces más de 4 veces el json_decode. Con un promedio de aproximadamente 1.5ms sobre 2.5ms.

Jelmer
fuente
3

Antes de tomar su decisión final, tenga en cuenta que el formato JSON no es seguro para las matrices asociativas; en su lugar json_decode(), las devolverá como objetos:

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

Salida es:

Array
(
    [Frodo] => hobbit
    [Gimli] => dwarf
    [Gandalf] => wizard
)
stdClass Object
(
    [Frodo] => hobbit
    [Gimli] => dwarf
    [Gandalf] => wizard
)
demasiado php
fuente
De hecho, tienes razón. Quiero decir, ¡ es una notación de objeto Javascript después de todo! Afortunadamente, si sabe que lo que codificó usando json_encodeera una matriz asociativa, puede forzarlo fácilmente a una matriz de la siguiente manera: $json = json_encode($some_assoc_array); $back_to_array = (array)json_decode($json);También es bueno tener en cuenta que puede acceder a los objetos de la misma manera que las matrices en PHP, por lo que en un escenario típico, uno ni siquiera sabría la diferencia. Buen punto sin embargo!
KyleFarris
30
@toomuchphp, lo siento pero estás equivocado. Hay un segundo parámetro para json_decode 'bool $ assoc = false' que hace que json_decode produzca una matriz. @KyleFarris, esto también debería ser más rápido que usar el typecast para la matriz.
janpio
La respuesta no es correcta. cuando se utiliza true como segundo parámetro de función, json_decode () devolverá matrices asociativas en lugar de objetos.
Marvin Saldinger
3

Primero, cambié el script para hacer más benchmarking (y también hacer 1000 ejecuciones en lugar de 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';
}

Usé esta compilación de PHP 7:

PHP 7.0.14 (cli) (construido: 18 de enero de 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, por Zend Technologies

Y mis resultados fueron:

serialize () (victorias: 999) fue aproximadamente 10.98% más rápido que json_encode () unserialize () (victorias: 987) fue aproximadamente 33.26% más rápido que json_decode () unserialize () (victorias: 987) fue aproximadamente 48.35% más rápido que array json_decode ()

Así que claramente , serializar / unserialize es el más rápido método, mientras que json_encode / decodificación es el más portátil.

Si considera un escenario en el que lee / escribe datos serializados 10 veces o más de lo que necesita enviar o recibir de un sistema que no sea PHP, TODAVÍA es mejor usar serializar / deserializar y tener json_encode o json_decode antes de la serialización en términos de tiempo.

Shawn Tolidano
fuente
2

Mira los resultados aquí (perdón por el truco que pone el código PHP en el cuadro de código JS):

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

RESULTADOS: serialize()y unserialize()ambos son significativamente más rápidos en PHP 5.4 en matrices de diferentes tamaños.

Hice un script de prueba en datos del mundo real para comparar json_encode vs serialize y json_decode vs unserialize. La prueba se ejecutó en el sistema de almacenamiento en caché de un sitio de comercio electrónico en producción. Simplemente toma los datos que ya están en el caché, y prueba los tiempos para codificar / decodificar (o serializar / deserializar) todos los datos y los pongo en una tabla fácil de ver.

Ejecuté esto en un servidor de alojamiento compartido PHP 5.4.

Los resultados fueron muy concluyentes de que para estos conjuntos de datos grandes y pequeños, serializar y no serializar fueron los claros ganadores. En particular para mi caso de uso, json_decode y unserialize son los más importantes para el sistema de almacenamiento en caché. Unserialize fue casi un ganador ubicuo aquí. Por lo general, era de 2 a 4 veces (a veces 6 o 7 veces) tan rápido como json_decode.

Es interesante notar la diferencia en los resultados de @ peter-bailey.

Aquí está el código PHP utilizado para generar los resultados:

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

solo para su información: si desea serializar sus datos en algo fácil de leer y comprender como JSON pero con más compresión y mayor rendimiento, debe consultar el paquete de mensajes.

Conejera
fuente
2
Si es solo un FYI, será mejor que lo pongas como comentario.
tecnófilo
0

JSON es mejor si desea hacer una copia de seguridad de los datos y restaurarlos en una máquina diferente o mediante FTP.

Por ejemplo, con serializar si almacena datos en un servidor de Windows, descárguelos a través de FTP y restaure en uno de Linux, ya no podría funcionar debido a la codificación de caracteres, porque serializar almacena la longitud de las cadenas y en Unicode > La transcodificación UTF-8 de un carácter de 1 byte podría convertirse en 2 bytes de longitud, lo que ocasionaría la falla del algoritmo.

Informate.it
fuente
0

THX - para este código de referencia:

Mis resultados en la matriz que uso para la configuración son los siguientes: JSON codificado en 0.0031511783599854 segundos
PHP serializado en 0.0037961006164551 segundos
json_encode()fue aproximadamente 20.47% más rápido que serialize() JSON codificado en 0.0070841312408447 segundos
PHP serializado en 0.0035839080810547 segundos
unserialize()fue aproximadamente 97.66% más rápido quejson_encode()

Entonces, pruébelo con sus propios datos.

mk182
fuente
¿Quieres decir que json_decode () en "unserialize () fue aproximadamente un 97,66% más rápido que json_encode ()", sí?
Meezaan-ud-Din
0

Si para resumir lo que dice la gente aquí, json_decode / encode parece más rápido que serializar / deserializar PERO Si hace var_dump, se cambia el tipo del objeto serializado. Si por alguna razón desea conservar el tipo, ¡vaya a serializar!

(intente, por ejemplo, stdClass vs array)

serializar / deserializar:

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' => 

codificación / decodificación json

Array cache:
object(stdClass)[7]
  public 'a' => string '1' (length=1)
  public 'b' => int 2
Object cache:
object(stdClass)[8]
  public 'field1' => int 123
This cache:
object(stdClass)[8]

Como puede ver, json_encode / decode convierte todo a stdClass, lo que no es tan bueno, la información del objeto se perdió ... Así que decida según las necesidades, especialmente si no se trata solo de matrices ...

David Constantine
fuente
Solo una nota: la mayoría de las otras respuestas dicen que serializar / deserializar es más rápido.
Ecker00
-3

Te sugiero que uses Super Cache, que es un mecanismo de caché de archivos que no usará json_encodeo serialize. Es simple de usar y realmente rápido en comparación con otros mecanismos de caché 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();
?>
shabeer
fuente
-1. Si bien podría ser una mejor solución, ninguna parte de esta respuesta en realidad responde a la pregunta del OP. En el futuro, quizás intente responder la pregunta, pero deje una sugerencia en el fondo de que una solución alternativa podría valer la pena.
starbeamrainbowlabs