Método preferido para almacenar matrices PHP (json_encode vs serialize)
Necesito almacenar una matriz asociativa multidimensional de datos en un archivo plano para fines de almacenamiento en caché. Es posible que ocasionalmente me encuentre con 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? Miré a mi alrededor y parece que en las versiones más recientes de PHP (5.3), json_decode
en realidad es más rápido que unserialize
.
Actualmente me estoy inclinando por almacenar la matriz como JSON porque creo que es más fácil de leer para un humano si es necesario, se puede usar tanto en PHP como en JavaScript con muy poco esfuerzo y, por lo que he leído, incluso podría serlo. más rápido de decodificar (aunque no estoy seguro acerca de la codificación).
¿Alguien sabe de algún peligro? ¿Alguien tiene buenos puntos de referencia para mostrar los beneficios de rendimiento de cualquiera de los métodos?
Depende de tus prioridades.
Si el rendimiento es su característica de conducción absoluta, entonces utilice el más rápido. Solo asegúrese de comprender completamente las diferencias antes de tomar una decisión.
- A diferencia de
serialize()
usted, necesita 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 puedes aprovechar
__sleep()
y__wakeup()
con JSON - De forma predeterminada, solo las propiedades públicas se serializan con JSON. (
PHP>=5.4
Puedes implementar JsonSerializable para cambiar este comportamiento). - JSON es más portátil
Y probablemente haya algunas otras diferencias en las que no puedo pensar en este momento.
Una prueba de velocidad sencilla 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';
}
JSON es más simple y rápido que el formato de serialización de PHP y debe usarse a menos que :
- Estás almacenando matrices profundamente anidadas:
json_decode()
"Esta función devolverá falso si los datos codificados en JSON tienen más de 127 elementos". - Estás almacenando objetos que deben deserializarse como la clase correcta.
- Estás interactuando con versiones antiguas de PHP que no son compatibles con json_decode
Escribí una publicación de blog sobre este tema: " Almacenar en caché una matriz grande: ¿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.
También podría interesarle 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 de "cadena" serializado: 13993
PHP nativo:
- PHP serializado en 2.9125759601593 segundos
- PHP no serializado en 6.4348418712616 segundos
- Tamaño de "cadena" serializado: 20769
Igbinario:
- WIN igbinary serializado en 1.6099879741669 segundos
- WIN igbinrary no serializado en 4.7737920284271 segundos
- WIN serializado "Cadena" Tamaño: 4467
Por lo tanto, es más rápido igbinary_serialize() e igbinary_unserialize() y utiliza menos espacio en disco.
Utilicé el código fillArray(0, 3) como se indicó anteriormente, pero hice que las claves de la matriz fueran cadenas más largas.
igbinary puede almacenar los mismos tipos de datos que la serialización nativa de PHP (por lo que no hay problema con los objetos, etc.) y puede decirle a PHP5.3 que lo use para el manejo de sesiones si así lo desea.
Véase también http://ilia.ws/files/zendcon_2010_hidden_features.pdf - específicamente las diapositivas 14/15/16