Méthode préférée pour stocker les tableaux PHP (json_encode vs serialize)

608

J'ai besoin de stocker un tableau associatif multidimensionnel de données dans un fichier plat à des fins de mise en cache. Je pourrais parfois rencontrer le besoin de le convertir en JSON pour une utilisation dans mon application Web, mais la grande majorité du temps, j'utiliserai le tableau directement en PHP.

Serait-il plus efficace de stocker le tableau en JSON ou en tant que tableau sérialisé PHP dans ce fichier texte? J'ai regardé autour de moi et il semble que dans les dernières versions de PHP (5.3), json_decodec'est en fait plus rapide que unserialize.

Je penche actuellement vers le stockage du tableau en JSON car je pense qu'il est plus facile à lire par un humain si nécessaire, il peut être utilisé à la fois en PHP et en JavaScript avec très peu d'effort, et d'après ce que j'ai lu, il pourrait même être plus rapide à décoder (cependant pas sûr de l'encodage).

Quelqu'un connaît-il des pièges? Quelqu'un a-t-il de bons repères pour montrer les avantages de performance de l'une ou l'autre méthode?

KyleFarris
la source

Réponses:

563

Cela dépend de vos priorités.

Si la performance est votre caractéristique de conduite absolue, utilisez certainement la plus rapide. Assurez-vous de bien comprendre les différences avant de faire un choix

  • Contrairement à serialize()vous devez ajouter un paramètre supplémentaire pour garder les caractères UTF-8 intacts: json_encode($array, JSON_UNESCAPED_UNICODE) (sinon il convertit les caractères UTF-8 en séquences d'échappement Unicode).
  • JSON n'aura aucune mémoire de ce qu'était la classe d'origine de l'objet (ils sont toujours restaurés en tant qu'instances de stdClass).
  • Vous ne pouvez pas exploiter __sleep()et __wakeup()avec JSON
  • Par défaut, seules les propriétés publiques sont sérialisées avec JSON. ( PHP>=5.4vous pouvez implémenter JsonSerializable pour changer ce comportement).
  • JSON est plus portable

Et il y a probablement quelques autres différences auxquelles je ne peux pas penser en ce moment.

Un test de vitesse simple pour comparer les deux

<?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
la source
31
"JSON convertit les caractères UTF-8 en séquences d'échappement unicode." Ce n'est plus nécessairement vrai: nous l'avons maintenant JSON_UNESCAPED_UNICODE.
TRiG
32
Nous voici presque 5 ans plus tard et j'ai relancé les tests (juste le json_encode) et c'est en moyenne 131% plus rapide que la sérialisation maintenant. Donc, il doit y avoir de très belles améliorations à cette fonction dans 5.4.x sur 5.3.x. Plus précisément, j'utilise 5.4.24 sur CentOS 6. Alors, oui pour JSON !!
KyleFarris
8
dans mon cas, nous encodons une fois et décodons beaucoup, nous avons donc comparé json_decode vs unserialize et les résultats ont été JSON décodés en 0,06662392616272 secondes <br> PHP non sérialisé en 0,093269109725952 secondes <br> json_decode () était environ 39,99% plus rapide que la désérialisation ()
AMB
21
Intéressant: si vous exécutez ce code sur 3v4l.org , les dernières versions de développement PHP7 exécutent serialize plus rapidement que json_encode: "serialize () était environ 76,53% plus rapide que json_encode ()"
marcvangend
21
2017, PHP 7.1 etserialize() was roughly 35.04% faster than json_encode()
Elias Soares
239

JSON est plus simple et plus rapide que le format de sérialisation de PHP et doit être utilisé sauf si :

  • Vous stockez des tableaux profondément imbriqués json_decode():: "Cette fonction retournera false si les données encodées JSON sont plus profondes que 127 éléments."
  • Vous stockez des objets qui doivent être non sérialisés en tant que classe correcte
  • Vous interagissez avec d'anciennes versions de PHP qui ne prennent pas en charge json_decode
Greg
la source
12
Très bonne réponse. Haha, 127 niveaux de profondeur semble un peu fou; heureusement, je ne fais que 2-3 au maximum. Avez-vous des données pour sauvegarder le fait que json_decode / json_encode est plus rapide que désérialisation / sérialisation?
KyleFarris
1
Je l'ai testé il y a quelque temps et json est sorti plus vite - je n'ai plus les données cependant.
Greg
47
"5.3.0 Ajout de la profondeur facultative. La profondeur de récursivité par défaut est passée de 128 à 512"
giorgio79
4
J'ajouterais un autre élément à la liste ci-dessus: json_encode () ne devrait pas être utilisé si vos données peuvent contenir des séquences d'octets UTF-8 invalides. Il renvoie simplement false pour ces données. Essayez par exemple: var_dump (json_encode ("\ xEF \ xEF"));
pako
2
Ce n'est pas vrai qu'il est plus rapide en général. Si vous avez un petit tableau avec environ ~ 500 entrées, la désérialisation / sérialisation est en fait 200 à 400% plus rapide que json_decode / json_encode (PHP 5.6.19)
Adam
59

J'ai écrit un article sur ce sujet: " Mettre en cache un grand tableau: JSON, serialize ou var_export? " . Dans cet article, il est montré que la sérialisation est le meilleur choix pour les baies de petite à grande taille. Pour les très grands tableaux (> 70 Mo), JSON est le meilleur choix.

Taco
la source
8
Le lien n'est plus disponible.
Martin Thoma
1
Merci, orignal, j'ai mis à jour le lien. Bien que l'article ait presque 6 ans et ne soit pas aussi précis pour les versions PHP actuelles.
Taco
J'ai fait quelques tests et fait une fonction simple pour le tester, avec de grands tableaux (fonction utilisée par Peter Bailey pour ceux-ci), json_encode()c'est environ 80% à 150% plus rapide ( ça monte et descend vraiment là-bas) serialize()qu'avec environ 300 itérations. Mais lorsque array("teams" => array(1 => array(4 arrays of players), 2 => array(4 arrays of players)))j'utilise les petits tableaux ( ), j'ai testé avec 750 000 itérations et serialize()est environ 6% à 10% plus rapide dans ce cas. Ma fonction prend le temps moyen pour toutes les itérations et les compare. Je pourrais l'afficher ici comme l'une des réponses
MiChAeLoKGB
si les données ne sont utilisées que par PHP, var_export est mon truc. Il suffit de faire attention aux éventuelles erreurs de syntaxe dans la pensée d'inclusion.
Gfra54
3
le blog n'existe plus
popeye
53

Vous pourriez aussi être intéressé par https://github.com/phadej/igbinary - qui fournit un «moteur» de sérialisation différent pour PHP.

Mes chiffres de performances aléatoires / arbitraires, en utilisant PHP 5.3.5 sur une plate-forme 64 bits, montrent:

JSON:

  • JSON encodé en 2.180496931076 secondes
  • JSON décodé en 9.8368630409241 secondes
  • taille "String" sérialisée: 13993

PHP natif:

  • PHP sérialisé en 2.9125759601593 secondes
  • PHP non sérialisé en 6,4348418712616 secondes
  • série "String" sérialisée: 20769

Igbinaire:

  • WIN igbinary sérialisé en 1,6099879741669 secondes
  • WIN igbinrary non sérialisé en 4,7737920284271 secondes
  • WIN sérialisé "String" Taille: 4467

Ainsi, il est plus rapide d'igbinary_serialize () et igbinary_unserialize () et utilise moins d'espace disque.

J'ai utilisé le code fillArray (0, 3) comme ci-dessus, mais j'ai rendu les clés de tableau plus longues.

igbinary peut stocker les mêmes types de données que la sérialisation native de PHP (donc pas de problème avec les objets, etc.) et vous pouvez dire à PHP5.3 de l'utiliser pour la gestion de session si vous le souhaitez.

Voir également http://ilia.ws/files/zendcon_2010_hidden_features.pdf - en particulier les diapositives 14/15/16

David Goodwin
la source
25

Y vient de tester le codage et le décodage sérialisé et json, plus la taille de la chaîne stockée.

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

Nous pouvons conclure que JSON code plus rapidement et produit une chaîne plus petite, mais la désérialisation est plus rapide pour décoder la chaîne.

Blunk
la source
6
Je ne sais pas pourquoi les gens font toujours des tests de performances avec un si petit ensemble de données. Ce faisant, vous avez tous les frais généraux qui ajoutent des erreurs à vos résultats. Et si les gens sont intéressés par les performances, c'est probablement parce qu'ils ont un très grand ensemble de données, car il est inutile de gagner une microseconde une fois.
Yann Sagon
1
Très souvent, j'itère sur de nombreux petits ensembles de données. Avec des centaines de petits ensembles de données, gagner 1 ms pour chacun est toujours intéressant.
Teson
@YannSagon Même avec de petits ensembles de données, il est logique de faire un test de performance. Comment savoir avant le test s'il ne s'agit que d'une micro seconde environ?
Adam
17

Si vous mettez en cache des informations que vous souhaiterez finalement "inclure" à un moment ultérieur, vous pouvez essayer d'utiliser var_export . De cette façon, vous ne prenez le coup que dans la "sérialisation" et non dans la "désérialisation".

Jordan S. Jones
la source
C'est probablement le moyen le plus rapide possible. J'ai écrit un exemple sur le SO "PHP - serialize / unserialize rapide ": stackoverflow.com/questions/2545455/…
dave1010
12

J'ai augmenté le test pour inclure les performances de désérialisation. Voici les chiffres que j'ai obtenus.

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 semble donc être plus rapide pour l'encodage mais lent pour le décodage. Cela peut donc dépendre de votre application et de ce que vous comptez faire le plus.

Jeff Whiting
la source
9

Sujet vraiment sympa et après avoir lu les quelques réponses, je souhaite partager mes expériences sur le sujet.

J'ai un cas d'utilisation où une table "énorme" doit être interrogée presque chaque fois que je parle à la base de données (ne demandez pas pourquoi, juste un fait). Le système de mise en cache de la base de données n'est pas approprié car il ne mettra pas en cache les différentes demandes, donc j'ai pensé aux systèmes de mise en cache php.

J'ai essayé apcumais cela ne correspondait pas aux besoins, la mémoire n'est pas assez fiable dans ce cas. L'étape suivante consistait à mettre en cache dans un fichier avec la sérialisation.

Le tableau a 14355 entrées avec 18 colonnes, ce sont mes tests et statistiques sur la lecture du cache sérialisé:

JSON:

Comme vous l'avez tous dit, le principal inconvénient de json_encode/ json_decodeest qu'il transforme tout en une StdClassinstance (ou un objet). Si vous avez besoin de le boucler, le transformer en un tableau est ce que vous ferez probablement, et oui, cela augmente le temps de transformation

temps moyen: 780,2 ms; utilisation de la mémoire: 41,5 Mo; taille du fichier cache: 3,8 Mo

Msgpack

@hutch mentionne msgpack . Joli site Web. Essayons-nous?

temps moyen: 497 ms; utilisation de la mémoire: 32 Mo; taille du fichier cache: 2,8 Mo

C'est mieux, mais nécessite une nouvelle extension; compiler des gens parfois effrayés ...

IgBinary

@GingerDog mentionne l' igbinary . Notez que j'ai défini le igbinary.compact_strings=Offcar je me soucie plus des performances de lecture que de la taille du fichier.

temps moyen: 411,4 ms; utilisation de la mémoire: 36,75 Mo; taille du fichier cache: 3,3 Mo

Mieux que le pack msg. Pourtant, celui-ci nécessite également une compilation.

serialize/unserialize

temps moyen: 477,2 ms; utilisation de la mémoire: 36,25 Mo; taille du fichier cache: 5,9 Mo

Meilleures performances que JSON, plus la baie est grande, plus lentement json_decode est , mais vous l'avez déjà fait.

Ces extensions externes réduisent la taille du fichier et semblent excellentes sur le papier. Les chiffres ne mentent pas *. Quel est l'intérêt de compiler une extension si vous obtenez presque les mêmes résultats que vous obtiendriez avec une fonction PHP standard?

On peut également en déduire qu'en fonction de vos besoins, vous choisirez quelque chose de différent de quelqu'un d'autre:

  • IgBinary est vraiment agréable et fonctionne mieux que MsgPack
  • Msgpack est meilleur pour compresser vos données (notez que je n'ai pas essayé l'option igbinary compact.string).
  • Vous ne voulez pas compiler? Utilisez des normes.

Voilà, une autre comparaison des méthodes de sérialisation pour vous aider à choisir celle-là!

* Testé avec PHPUnit 3.7.31, php 5.5.10 - décodage uniquement avec un disque dur standard et un ancien processeur dual core - en moyenne sur 10 tests de cas d'utilisation, vos statistiques peuvent être différentes

soyuka
la source
Pourquoi ne pas passer le drapeau à json_decode pour forcer le retour des tableaux?
Alex Yaroshevich
Parce que c'est lent. Je n'ai pas testé cela mais je pense que forcer simplement le changement de type depuis php est plus rapide.
soyuka
Je sais juste que la création de tableaux est beaucoup plus rapide que les objets en php.
Alex Yaroshevich
Donc, vous parlez json_decode($object, true), fondamentalement, cela fera la même chose que (array) json_decode($object)mais récursivement, ce serait donc le même comportement et cela aura un coût important dans les deux cas. Notez que je n'ai pas testé les différences de performances entre StdClasset arraymais ce n'est pas vraiment le point ici.
soyuka
Je suis sûr que c'est un autre coût car cela se fait à un niveau inférieur sans objets.
Alex Yaroshevich du
8

On dirait que sérialiser est celui que je vais utiliser pour 2 raisons:

  • Quelqu'un a souligné que la désérialisation est plus rapide que json_decode et qu'un cas de «lecture» semble plus probable qu'un cas «d'écriture».

  • J'ai eu des problèmes avec json_encode lorsque j'ai des chaînes avec des caractères UTF-8 invalides. Lorsque cela se produit, la chaîne finit par être vide, ce qui entraîne une perte d'informations.

urraka
la source
pouvez-vous s'il vous plaît élaborer votre dernier point avec un exemple
Naveen Saroye
6

J'ai testé cela très soigneusement sur un multi-hachage assez complexe et légèrement imbriqué avec toutes sortes de données (chaîne, NULL, entiers), et sérialiser / désérialiser s'est terminé beaucoup plus rapidement que json_encode / json_decode.

Le seul avantage que json a dans mes tests est sa taille plus compacte.

Celles-ci sont effectuées sous PHP 5.3.3, faites-moi savoir si vous souhaitez plus de détails.

Voici les résultats des tests puis le code pour les produire. Je ne peux pas fournir les données de test car cela révélerait des informations que je ne peux pas laisser sortir dans la nature.

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
la source
Je viens d'effectuer un test similaire avec PHP 5.4.12 et j'ai trouvé des résultats similaires: {un,} la sérialisation est plus rapide. Mes données sont des hachages imbriqués sur 3 niveaux (900k sérialisés).
sorpigal
6

J'ai également fait une petite référence. Mes résultats étaient les mêmes. Mais j'ai besoin des performances de décodage. Là où j'ai remarqué, comme l'ont dit quelques personnes ci-dessus aussi, unserializec'est plus rapide que json_decode. unserializeprend environ 60 à 70% du json_decodetemps. La conclusion est donc assez simple: lorsque vous avez besoin de performances dans le codage, utilisez json_encode, lorsque vous avez besoin de performances lors du décodage, utilisez unserialize. Parce que vous ne pouvez pas fusionner les deux fonctions, vous devez faire un choix là où vous avez besoin de plus de performances.

Ma référence en pseudo:

  • Définissez le tableau $ arr avec quelques clés et valeurs aléatoires
  • pour x <100; x ++; sérialiser et json_encode un array_rand de $ arr
  • pour y <1000; y ++; json_decode la chaîne codée json - temps de calcul
  • pour y <1000; y ++; désérialiser la chaîne sérialisée - temps de calcul
  • faire écho au résultat qui était plus rapide

En moyenne: unserialize a remporté 96 fois plus de 4 fois le json_decode. Avec une moyenne d'environ 1,5 ms sur 2,5 ms.

Jelmer
la source
3

Avant de prendre votre décision finale, sachez que le format JSON n'est pas sûr pour les tableaux associatifs - json_decode()les renverra en tant qu'objets à la place:

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

La sortie est:

Array
(
    [Frodo] => hobbit
    [Gimli] => dwarf
    [Gandalf] => wizard
)
stdClass Object
(
    [Frodo] => hobbit
    [Gimli] => dwarf
    [Gandalf] => wizard
)
trop de php
la source
En effet, vous avez raison. Je veux dire, il est Javascript objet notation après tout! Heureusement, si vous savez que ce que vous avez encodé en utilisant json_encodeétait un tableau associatif, vous pouvez facilement le forcer à revenir dans un tableau comme ceci: $json = json_encode($some_assoc_array); $back_to_array = (array)json_decode($json);il est également bon de noter que vous pouvez accéder aux objets de la même manière que les tableaux en PHP, donc dans un scénario typique, on ne connaîtrait même pas la différence. Bon point cependant!
KyleFarris
30
@toomuchphp, désolé mais vous vous trompez. Il existe un deuxième paramètre pour json_decode 'bool $ assoc = false' qui fait que json_decode produit un tableau. @KyleFarris, cela devrait également être plus rapide que d'utiliser le transtypage en tableau.
janpio
la réponse n'est pas correcte. lors de l'utilisation de true comme second paramètre de la fonction, json_decode () retournera des tableaux associatifs au lieu d'objets.
Marvin Saldinger
3

Tout d'abord, j'ai changé le script pour faire un peu plus de benchmarking (et aussi faire 1000 runs au lieu de 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';
}

J'ai utilisé cette version de PHP 7:

PHP 7.0.14 (cli) (build: 18 janvier 2017 19:13:23) (NTS) Copyright (c) 1997-2016 The PHP Group Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies with Zend OPcache v7.0.14, Copyright (c) 1999-2016, par Zend Technologies

Et mes résultats étaient:

serialize () (victoires: 999) était environ 10,98% plus rapide que json_encode () unserialize () (victoires: 987) était environ 33,26% plus rapide que json_decode () unserialize () (victoires: 987) était environ 48,35% plus rapide que le tableau json_decode ()

Il est donc clair que serialize / unserialize est la méthode la plus rapide , tandis que json_encode / decode est la plus portable.

Si vous envisagez un scénario dans lequel vous lisez / écrivez des données sérialisées 10 fois ou plus souvent que ce que vous devez envoyer ou recevoir depuis un système non PHP, vous feriez TOUJOURS mieux d'utiliser sérialiser / désérialiser et de l'avoir json_encode ou json_decode avant la sérialisation en termes de temps.

Shawn Tolidano
la source
2

Découvrez les résultats ici (désolé pour le piratage mettant le code PHP dans la boîte de code JS):

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

RÉSULTATS: serialize()et unserialize()sont tous deux beaucoup plus rapides en PHP 5.4 sur des tableaux de taille variable.

J'ai fait un script de test sur des données du monde réel pour comparer json_encode vs serialize et json_decode vs unserialize. Le test a été exécuté sur le système de mise en cache d'un site de commerce électronique en production. Il prend simplement les données déjà dans le cache et teste les temps pour encoder / décoder (ou sérialiser / désérialiser) toutes les données et je les mets dans un tableau facile à voir.

Je l'ai exécuté sur un serveur d'hébergement partagé PHP 5.4.

Les résultats ont été très concluants que pour ces grands et petits ensembles de données, la sérialisation et la désérialisation étaient les gagnants clairs. En particulier pour mon cas d'utilisation, json_decode et unserialize sont les plus importants pour le système de mise en cache. Unserialize était presque un gagnant omniprésent ici. Il était généralement 2 à 4 fois (parfois 6 ou 7 fois) aussi rapide que json_decode.

Il est intéressant de noter la différence de résultats de @ peter-bailey.

Voici le code PHP utilisé pour générer les résultats:

<?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
la source
1

juste un fyi - si vous voulez sérialiser vos données en quelque chose de facile à lire et à comprendre comme JSON mais avec plus de compression et de meilleures performances, vous devriez vérifier messagepack.

Clapier
la source
2
si c'est juste un fyi, vous feriez mieux de le mettre en commentaire.
technophyle
0

JSON est préférable si vous souhaitez sauvegarder des données et les restaurer sur une autre machine ou via FTP.

Par exemple, avec sérialiser si vous stockez des données sur un serveur Windows, téléchargez-les via FTP et restaurez-les sur un serveur Linux, cela ne pourrait plus fonctionner en raison du recodage du caractère, car sérialiser stocke la longueur des chaînes et dans l'Unicode > Le transcodage UTF-8 de certains caractères de 1 octet pourrait devenir long de 2 octets, ce qui ferait planter l'algorithme.

Informate.it
la source
0

THX - pour ce code de référence:

Mes résultats sur la baie que j'utilise pour la configuration sont comme des jachères: JSON encodé en 0,0031511783599854 secondes
PHP sérialisé en 0,0037961006164551 secondes
json_encode()était environ 20,47% plus rapide que serialize() JSON encodé en 0,0070841312408447 secondes
PHP sérialisé en 0,0035839080810547 secondes
unserialize()était environ 97,66% plus rapide quejson_encode()

Alors - testez-le sur vos propres données.

mk182
la source
Vous voulez dire que json_decode () dans "unserialize () était environ 97,66% plus rapide que json_encode ()", oui?
Meezaan-ud-Din
0

Si pour résumer ce que les gens disent ici, json_decode / encode semble plus rapide que serialize / unserialize MAIS Si vous faites var_dump le type de l'objet sérialisé est changé. Si pour une raison quelconque vous souhaitez conserver le type, optez pour la sérialisation!

(essayez par exemple stdClass vs array)

sérialiser / désérialiser:

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

codage / décodage 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]

Comme vous pouvez le voir, json_encode / decode convertit tout en stdClass, ce qui n'est pas si bon, les informations d'objet sont perdues ... Alors décidez en fonction des besoins, surtout s'il ne s'agit pas que de tableaux ...

David Constantine
la source
Juste une note: la plupart des autres réponses disent que la sérialisation / désérialisation est plus rapide.
Ecker00
-3

Je vous suggère d'utiliser Super Cache, qui est un mécanisme de cache de fichiers qui n'utilisera pas json_encodeouserialize . Il est simple à utiliser et très rapide par rapport aux autres mécanismes de 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();
?>
Shabeer
la source
-1. Bien que cela puisse être une meilleure solution, aucune partie de cette réponse ne répond réellement à la question du PO. À l'avenir, essayez peut-être de répondre à la question, mais en laissant une suggestion en bas qu'une solution alternative pourrait être étudiée.
starbeamrainbowlabs