Método preferido para armazenar matrizes PHP (json_encode vs serialize)

608

Preciso armazenar uma matriz associativa multidimensional de dados em um arquivo simples para fins de armazenamento em cache. Ocasionalmente, deparo-me com a necessidade de convertê-lo em JSON para uso no meu aplicativo da Web, mas na maioria das vezes utilizarei a matriz diretamente no PHP.

Seria mais eficiente armazenar a matriz como JSON ou como uma matriz serializada PHP neste arquivo de texto? Eu olhei em volta e parece que, nas versões mais recentes do PHP (5.3), json_decodeé realmente mais rápido que unserialize.

Atualmente, estou inclinado a armazenar a matriz como JSON, pois acho que é mais fácil ler por um ser humano, se necessário. Ele pode ser usado em PHP e JavaScript com muito pouco esforço e, pelo que li, pode até ser mais rápido para decodificar (embora não tenha certeza sobre a codificação).

Alguém sabe de alguma armadilha? Alguém tem boas referências para mostrar os benefícios de desempenho de qualquer um dos métodos?

KyleFarris
fonte

Respostas:

563

Depende das suas prioridades.

Se o desempenho é a sua característica de condução absoluta, use sempre a mais rápida. Apenas certifique-se de ter um entendimento completo das diferenças antes de fazer uma escolha

  • Ao contrário, serialize()você precisa adicionar um parâmetro extra para manter os caracteres UTF-8 intocados: json_encode($array, JSON_UNESCAPED_UNICODE) (caso contrário, converte caracteres UTF-8 em seqüências de escape Unicode).
  • JSON não terá memória da classe original do objeto (eles sempre são restaurados como instâncias de stdClass).
  • Você não pode aproveitar __sleep()e __wakeup()com JSON
  • Por padrão, apenas propriedades públicas são serializadas com JSON. ( PHP>=5.4você pode implementar o JsonSerializable para alterar esse comportamento).
  • JSON é mais portátil

E provavelmente há outras diferenças em que não consigo pensar no momento.

Um teste de velocidade simples para comparar os dois

<?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
fonte
31
"JSON converte caracteres UTF-8 em seqüências de escape unicode." Não é mais necessariamente verdade: agora temos JSON_UNESCAPED_UNICODE.
TRiG 24/11/12
32
Aqui estamos quase 5 anos depois e eu executei os testes novamente (apenas o json_encode) e está em média 131% mais rápido do que o serializado agora. Portanto, deve haver algumas melhorias bastante agradáveis ​​nessa função no 5.4.x sobre o 5.3.x. Especificamente, estou executando o 5.4.24 no CentOS 6. Então, sim para o JSON !!
precisa saber é o seguinte
8
no meu caso, codificamos uma vez e decodificamos muito, portanto, comparamos o json_decode vs unserialize e os resultados foram JSON dcodificados em 0,06662392616272 segundos <br> PHP não serializado em 0,093269109725952 segundos <br> json_decode () foi aproximadamente 39,99% mais rápido que unserialize ()
AMB
21
Interessante: se você executar esse código em 3v4l.org , o mais recente desenvolvimento PHP7 constrói executar serialize mais rápido do que json_encode: "serialize () foi de aproximadamente 76,53% mais rápido do que json_encode ()"
marcvangend
21
2017, PHP 7.1 eserialize() was roughly 35.04% faster than json_encode()
Elias Soares
239

JSON é mais simples e mais rápido que o formato de serialização do PHP e deve ser usado, a menos que :

  • Você está armazenando matrizes profundamente aninhadas json_decode():: "Esta função retornará false se os dados codificados em JSON tiverem mais de 127 elementos".
  • Você está armazenando objetos que precisam ser desserializados como a classe correta
  • Você está interagindo com versões antigas do PHP que não suportam json_decode
Greg
fonte
12
Ótima resposta. Haha, 127 níveis de profundidade parece um pouco insano; felizmente, eu só vou fazer 2-3 no máximo. Você tem algum dado para fazer backup do fato de que json_decode / json_encode é mais rápido que desserializar / serializar?
KyleFarris
1
Eu testei há um tempo atrás e o json saiu mais rápido - embora eu não tenha mais os dados.
28411 Greg
47
"5.3.0 Adicionada a profundidade opcional. A profundidade de recursão padrão foi aumentada de 128 para 512"
giorgio79
4
Eu adicionaria mais um item à lista acima: json_encode () não deve ser usado se seus dados puderem conter seqüências de bytes UTF-8 inválidas. Simplesmente retorna false para esses dados. Tente por exemplo: var_dump (json_encode ("\ xEF \ xEF"));
pako
2
Não é verdade que seja mais rápido em geral. Se você tem um pequeno conjunto com cerca de ~ 500 entradas, então unserialize / serialize é realmente 200-400% mais rápido, então json_decode / json_encode (PHP 5.6.19)
Adam
59

Eu escrevi uma postagem no blog sobre este assunto: " Cache de uma grande matriz: JSON, serialize ou var_export? " . Neste post, é mostrado que serializar é a melhor opção para matrizes de pequeno a grande porte. Para matrizes muito grandes (> 70 MB), o JSON é a melhor escolha.

Taco
fonte
8
O link não está mais disponível.
Martin Thoma
1
Obrigado, alce, eu atualizei o link. Embora o artigo tenha quase 6 anos e possa não ser tão preciso para as versões atuais do PHP.
Taco
Fiz alguns testes e fiz uma função simples para testá-lo, com grandes matrizes (função usada de Peter Bailey para esses) json_encode()é cerca de 80% a 150% mais rápida (realmente está subindo e descendo) do que serialize(), com cerca de 300 iterações. Mas, ao usar matrizes menores ( array("teams" => array(1 => array(4 arrays of players), 2 => array(4 arrays of players)))), testei com 750.000 iterações e serialize()é cerca de 6% a 10% mais rápido nesse caso. Minha função leva os tempos médios para todas as iterações e as compara. Eu poderia publicá-la aqui como uma das respostas
MiChAeLoKGB
se os dados são usados ​​apenas pelo PHP, var_export é a minha coisa. Só precisa ter cuidado com possíveis erros de sintaxe no pensamento de inclusão.
Gfra54
3
blogue não existe mais
Popeye
53

Você também pode estar interessado em https://github.com/phadej/igbinary - que fornece um 'mecanismo' de serialização diferente para PHP.

Meus números aleatórios / arbitrários de 'desempenho', usando o PHP 5.3.5 em uma plataforma de 64 bits, mostram:

JSON:

  • JSON codificado em 2.180496931076 segundos
  • JSON decodificado em 9.8368630409241 segundos
  • tamanho de "String" serializado: 13993

PHP nativo:

  • PHP serializado em 2,9125759601593 segundos
  • PHP não serializado em 6,4348418712616 segundos
  • tamanho de "String" serializado: 20769

Igbinário:

  • WIN igbinary serializado em 1.6099879741669 segundos
  • Igbinrary WIN não serializado em 4,7737920284271 segundos
  • WIN serializado "String" Tamanho: 4467

Portanto, é mais rápido igbinary_serialize () e igbinary_unserialize () e usa menos espaço em disco.

Usei o código fillArray (0, 3) como acima, mas fiz com que as chaves da matriz fossem mais longas.

O igbinary pode armazenar os mesmos tipos de dados que o serializado nativo do PHP pode (portanto, não há problema com objetos, etc.) e você pode dizer ao PHP5.3 para usá-lo no tratamento de sessões, se assim o desejar.

Veja também http://ilia.ws/files/zendcon_2010_hidden_features.pdf - especificamente slides 14/15/16

David Goodwin
fonte
25

Você acabou de testar serializado e json codificar e decodificar, mais o tamanho que ele levará para a cadeia armazenada.

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 o JSON codifica mais rapidamente e resulta em uma string menor, mas a desserialização é mais rápida para decodificar a string.

Blunk
fonte
6
Não sei por que as pessoas sempre fazem testes de desempenho com um conjunto de dados tão pequeno. Fazendo isso, você tem toda a sobrecarga que adiciona erros aos seus resultados. E se as pessoas estão interessadas em desempenho, provavelmente é porque elas têm um conjunto de dados muito grande, porque não faz sentido ganhar um microsseg uma vez.
Yann Sagon
1
Frequentemente, eu itero sobre muitos conjuntos de dados pequenos. Com centenas de pequenos conjuntos de dados, o ganho de 1mS para cada um ainda é interessante.
Teson
@YannSagon Mesmo com conjuntos de dados pequenos, faz sentido fazer um teste de desempenho. Como você deve saber antes do teste se é apenas um microssegundo?
Adam
17

Se você estiver armazenando em cache as informações que desejará "incluir" posteriormente, tente usar var_export . Dessa forma, você recebe apenas o hit no "serializar" e não no "desserializar".

Jordan S. Jones
fonte
Esta é provavelmente a maneira mais rápida possível. Eu escrevi um exemplo no SO "PHP - rápido serialize / unserialize": stackoverflow.com/questions/2545455/...
dave1010
12

Aumentei o teste para incluir o desempenho de desserialização. Aqui estão os números que eu tenho.

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

Então, o json parece ser mais rápido para codificação, mas lento na decodificação. Portanto, isso pode depender da sua aplicação e do que você espera fazer mais.

Jeff Whiting
fonte
9

Tópico muito bom e depois de ler as poucas respostas, quero compartilhar minhas experiências sobre o assunto.

Eu tenho um caso de uso em que alguma tabela "enorme" precisa ser consultada quase toda vez que eu falo com o banco de dados (não pergunte o porquê, apenas um fato). O sistema de armazenamento em cache do banco de dados não é apropriado, pois não armazenará em cache as diferentes solicitações, por isso pensei em sistemas de cache php.

eu tentei apcu mas não atendia às necessidades, a memória não é suficientemente confiável nesse caso. O próximo passo foi armazenar em cache um arquivo com serialização.

A tabela possui 14355 entradas com 18 colunas; esses são meus testes e estatísticas sobre a leitura do cache serializado:

JSON:

Como você disse, o grande inconveniente com json_encode/ json_decodeé que ele transforma tudo em uma StdClassinstância (ou Objeto). Se você precisar fazer um loop, transformá-lo em uma matriz é o que você provavelmente fará, e sim, está aumentando o tempo de transformação

tempo médio: 780,2 ms; uso de memória: 41,5MB; tamanho do arquivo em cache: 3,8MB

Msgpack

O @hutch menciona o msgpack . Site bonito. Vamos tentar, não é?

tempo médio: 497 ms; uso de memória: 32MB; tamanho do arquivo em cache: 2,8MB

Isso é melhor, mas requer uma nova extensão; compilando pessoas às vezes com medo ...

IgBinary

@GingerDog menciona igbinary . Observe que eu configurei o igbinary.compact_strings=Offporque me preocupo mais com a leitura do que com o tamanho do arquivo.

tempo médio: 411,4 ms; uso de memória: 36,75 MB; tamanho do arquivo em cache: 3,3MB

Melhor que o pacote msg. Ainda assim, este também requer compilação.

serialize/unserialize

tempo médio: 477,2 ms; uso de memória: 36,25MB; tamanho do arquivo em cache: 5,9MB

Melhores desempenhos que o JSON, quanto maior a matriz, mais lento json_decodeé, mas você já é novo nisso.

Essas extensões externas estão diminuindo o tamanho do arquivo e parecem ótimas no papel. Os números não mentem *. Qual o sentido de compilar uma extensão se você obtiver quase os mesmos resultados que obteria com uma função PHP padrão?

Também podemos deduzir que, dependendo de suas necessidades, você escolherá algo diferente de outra pessoa:

  • IgBinary é muito bom e tem um desempenho melhor que MsgPack
  • Msgpack é melhor na compactação de seus dados (observe que eu não tentei a opção igbinary compact.string).
  • Não quer compilar? Use padrões.

É isso aí, outra comparação de métodos de serialização para ajudar você a escolher esse!

* Testado com PHPUnit 3.7.31, php 5.5.10 - somente decodificando com um hardrive padrão e uma CPU dual core antiga - números médios em 10 testes de casos de uso iguais, suas estatísticas podem ser diferentes

soyuka
fonte
Por que não passar o sinalizador para json_decode para forçar o retorno de matrizes?
Alex Yaroshevich
Porque é lento. Não testei isso, mas acho que simplesmente forçar a alteração de tipo do php é mais rápido.
soyuka 24/11/14
Eu apenas sei que criar matrizes muito mais rápido que objetos em php.
Alex Yaroshevich
Então você está falando json_decode($object, true), basicamente, ele fará o mesmo, (array) json_decode($object)mas recursivamente, para que seja o mesmo comportamento e tenha um custo significativo nos dois casos. Observe que eu não testei as diferenças de desempenho entre StdClasse, arraymas esse não é realmente o ponto aqui.
soyuka 25/11
Tenho certeza de que é outro custo, porque é feito em um nível inferior sem objetos.
Alex Yaroshevich
8

Parece que serializar é o que eu vou usar por 2 razões:

  • Alguém apontou que a desserialização é mais rápida que json_decode e um caso de 'leitura' parece mais provável que um caso de 'gravação'.

  • Eu tive problemas com json_encode ao ter strings com caracteres UTF-8 inválidos. Quando isso acontece, a string acaba vazia, causando perda de informações.

urraka
fonte
você pode, por favor, elaborar seu último ponto com um exemplo
Naveen Saroye 26/11/19
6

Eu testei isso minuciosamente em um multi-hash bastante complexo e levemente aninhado, com todos os tipos de dados (string, NULL, inteiros), e serialize / unserialize acabou muito mais rápido que json_encode / json_decode.

A única vantagem que o json tem nos meus testes foi o tamanho 'compactado' menor.

Isso é feito no PHP 5.3.3, deixe-me saber se você deseja mais detalhes.

Aqui estão os resultados dos testes e o código para produzi-los. Não posso fornecer os dados do teste, pois revelariam informações que não posso deixar sair na natureza.

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
fonte
Acabei de executar um teste semelhante com o PHP 5.4.12 e encontrei resultados semelhantes: {un,} serialize é mais rápido. Meus dados são hashes aninhados em 3 níveis de profundidade (900k serializados).
sorpigal
6

Também fiz uma pequena referência. Meus resultados foram os mesmos. Mas preciso do desempenho da decodificação. Onde eu notei, como algumas pessoas acima disseram também, unserializeé mais rápido que json_decode. unserializeleva aproximadamente 60-70% do json_decodetempo. Portanto, a conclusão é bastante simples: quando você precisar de desempenho na codificação, use json_encode, quando precisar de desempenho ao decodificar, use unserialize. Como você não pode mesclar as duas funções, você deve escolher onde precisa de mais desempenho.

Minha referência em pseudo:

  • Defina a matriz $ arr com algumas chaves e valores aleatórios
  • para x <100; x ++; serialize e json_encode um array_rand de $ arr
  • para y <1000; y ++; json_decode a sequência codificada json - tempo de cálculo
  • para y <1000; y ++; desserializar a sequência serializada - tempo de cálculo
  • ecoar o resultado que foi mais rápido

Em avarage: unserialize ganhou 96 vezes mais de 4 vezes o json_decode. Com uma média de aproximadamente 1.5ms sobre 2.5ms.

Jelmer
fonte
3

Antes de tomar sua decisão final, lembre-se de que o formato JSON não é seguro para matrizes associativas - as json_decode()retornará como objetos:

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

A saída é:

Array
(
    [Frodo] => hobbit
    [Gimli] => dwarf
    [Gandalf] => wizard
)
stdClass Object
(
    [Frodo] => hobbit
    [Gimli] => dwarf
    [Gandalf] => wizard
)
muito php
fonte
Na verdade, você está certo. Quero dizer, é notação de objeto Javascript afinal! Felizmente, se você sabe que o que você codificou usando json_encodeera uma matriz associativa, pode facilmente forçá-la novamente a uma matriz da seguinte forma: $json = json_encode($some_assoc_array); $back_to_array = (array)json_decode($json);Também é bom observar que você pode acessar os objetos da mesma maneira que as matrizes no PHP, em um cenário típico, ninguém sequer saberia a diferença. Bom ponto!
KyleFarris
30
@toomuchphp, desculpe, mas você está errado. Existe um segundo parâmetro para json_decode 'bool $ assoc = false' que faz com que json_decode produza uma matriz. @KyleFarris, isso também deve ser mais rápido do que usar o typecast na matriz.
janpio
a resposta não está correta. ao usar true como segundo parâmetro da função, json_decode () retornará matrizes associativas em vez de objetos.
Marvin Saldinger 07/07/2015
3

Primeiro, mudei o script para fazer mais alguns testes comparativos (e também fazer 1000 execuções em vez de apenas 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';
}

Eu usei essa compilação do PHP 7:

PHP 7.0.14 (cli) (compilado: 18 de janeiro de 2017 19:13:23) (NTS) Copyright (c) 1997-2016 O PHP Group Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies com Zend OPcache v7.0.14, Copyright (c) 1999-2016, da Zend Technologies

E meus resultados foram:

serialize () (wins: 999) foi aproximadamente 10,98% mais rápido que json_encode () unserialize () (wins: 987) foi aproximadamente 33,26% mais rápido que json_decode () unserialize () (wins: 987) foi aproximadamente 48,35% mais rápido que o array json_decode ()

Tão claramente que serializar / desserializar é o método mais rápido , enquanto json_encode / decode é o mais portátil.

Se você considerar um cenário em que lê / grava dados serializados 10x ou mais frequentemente do que o necessário para enviar ou receber a partir de um sistema que não seja PHP, ainda é melhor usar serializar / desserializar e tê-lo json_encode ou json_decode antes da serialização em termos de tempo.

Shawn Tolidano
fonte
2

Confira os resultados aqui (desculpe pelo hack colocando o código PHP na caixa de código JS):

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

RESULTADOS: serialize()e unserialize()são significativamente mais rápidos no PHP 5.4 em matrizes de tamanhos variados.

Eu fiz um script de teste em dados do mundo real para comparar json_encode vs serialize e json_decode vs unserialize. O teste foi executado no sistema de cache de um site de comércio eletrônico em produção. Ele simplesmente pega os dados já no cache e testa os tempos para codificar / decodificar (ou serializar / desserializar) todos os dados e eu os coloco em uma tabela fácil de ver.

Eu executei isso no servidor de hospedagem compartilhada PHP 5.4.

Os resultados foram muito conclusivos que, para esses conjuntos de dados grandes e pequenos, serializar e desserializar foram os vencedores. Especialmente para o meu caso de uso, o json_decode e unserialize são os mais importantes para o sistema de armazenamento em cache. Unserialize foi quase um vencedor onipresente aqui. Geralmente era de 2 a 4 vezes (às vezes 6 ou 7) mais rápido que json_decode.

É interessante notar a diferença nos resultados de @ peter-bailey.

Aqui está o código PHP usado para gerar os 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
fonte
1

apenas um fyi - se você deseja serializar seus dados para algo fácil de ler e entender como JSON, mas com mais compactação e desempenho superior, consulte o pacote de mensagens.

Hutch
fonte
2
se for apenas um fyi, é melhor colocar isso como um comentário.
31516
0

JSON é melhor se você deseja fazer backup de dados e restaurá-los em uma máquina diferente ou via FTP.

Por exemplo, com serialize, se você armazenar dados em um servidor Windows, faça o download via FTP e restaure-o em um servidor Linux, pois não funcionou mais devido à recodificação de caracteres, porque serialize armazena o comprimento das strings e no Unicode > A transcodificação UTF-8 de um caractere de 1 byte pode ter 2 bytes de comprimento, causando a falha do algoritmo.

Informate.it
fonte
0

THX - para este código de referência:

Meus resultados na matriz que eu uso para configuração são os seguintes: JSON codificado em 0,0031511783599854 segundos
PHP serializado em 0,0037961006164551 segundos
json_encode()foi aproximadamente 20,47% mais rápido que serialize() JSON codificado em 0,0070841312408447 segundos
PHP serializado em 0,0035839080810547 segundos
unserialize()foi 97,66 % mais rápido quejson_encode()

Então - teste com seus próprios dados.

mk182
fonte
Você quer dizer que json_decode () em "unserialize () foi aproximadamente 97,66% mais rápido que json_encode ()", sim?
Meezaan-ud-Din 01/09/14
0

Se, para resumir o que as pessoas dizem aqui, json_decode / encode parece mais rápido que serializar / desserializar, MAS Se você fizer var_dump, o tipo do objeto serializado será alterado. Se, por algum motivo, você quiser manter o tipo, vá em serialize!

(tente por exemplo stdClass vs array)

serializar / desserializar:

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]

Como você pode ver, o json_encode / decode converte tudo em stdClass, o que não é bom, as informações do objeto são perdidas ... Portanto, decida com base nas necessidades, especialmente se não forem apenas matrizes ...

David Constantine
fonte
Apenas uma observação: a maioria das outras respostas diz que serializar / desserializar é mais rápido.
precisa saber é o seguinte
-3

Eu sugiro que você use o Super Cache, que é um mecanismo de cache de arquivos que não usará json_encodeou serialize. É simples de usar e muito rápido em comparação com outro mecanismo de cache do 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
fonte
-1. Embora possa ser uma solução melhor, nenhuma parte dessa resposta realmente responde à pergunta do OP. No futuro, talvez tente responder à pergunta, mas deixe uma sugestão no fundo de que uma solução alternativa pode valer a pena investigar.
Starbeamrainbowlabs 15/08/19