PHP dizileri saklamak için tercih edilen yöntem (serialize vs json_encode)

15 Cevap php

Ben önbelleğe alma amacıyla düz bir dosya veri çok boyutlu bir ilişkisel dizi saklamak gerekir. Bazen benim web uygulaması kullanılmak ama PHP doğrudan dizi kullanarak olacak zamanın büyük çoğunluğu için JSON dönüştürmek için ihtiyaç rastlamak olabilir.

JSON veya bu metin dosyası içerisinde bir PHP tefrika dizi gibi dizi depolamak için daha verimli olacaktır? Etrafa baktım ve PHP (5.3) en yeni sürümlerinde, json_decode aslında unserialize daha hızlı gibi görünüyor.

Ben gerekirse, çok az çaba ile PHP ve JavaScript hem kullanılabilir, ve ben okudum ne, hatta olabilecek bir insan tarafından okunması en kolay hissediyorum ben şu JSON olarak diziyi saklamak doğru eğilerek ediyorum (gerçi, kodlama hakkında emin değilim) çözmek için daha hızlı.

Herkes herhangi tuzaklar biliyor mu? Herkes yöntemi ya performans avantajlarını göstermek için iyi kriterler var?

Herhangi bir yardım için şimdiden teşekkür ederiz.

15 Cevap

Önceliklerinizi bağlıdır.

Performans size mutlak sürüş karakteristiği ise, o zaman elbette hızlı birini kullanın. Sadece bir seçim yapmadan önce emin farklılıkları tam bir anlayış var olun

  • JSON unicode kaçış dizilerinin UTF-8 karakterleri dönüştürür. serialize() yok.
  • JSON nesnenin özgün sınıf (onlar hep stdClass örnekleri olarak restore edilmiştir) ne hiçbir belleğe sahip olacak.
  • Sen __sleep() kaldıraç ve __wakeup() ile JSON edemez
  • Sadece kamu özellikleri ile JSON serileştirilir
  • JSON daha taşınabilir

Ve ben şu anda düşünemiyorum birkaç diğer farklılıklar muhtemelen var.

Iki karşılaştırmak için basit bir hız testi

<?php

ini_set( 'display_errors', 1 );
error_reporting( E_ALL );

//  Make a bit, 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<br>";

//  Time serialization
$start = microtime( true );
serialize( $testArray );
$serializeTime = microtime( true ) - $start;
echo "PHP serialized in $serializeTime seconds<br>";

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

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 PHP'nin seri hale getirme biçimi daha basit ve daha hızlı olduğunu ve kullanılması gerektiğini unless:

  • You're storing deeply nested arrays: json_decode(): "This function will return false if the JSON encoded data is deeper than 127 elements."
  • Sen doğru sınıf olarak dizgilenmemiş gereken nesneleri depolamak
  • Sen json_decode desteklemeyen eski PHP sürümleri ile etkileşim konum

"Cache a large array: JSON, serialize or var_export?:" Ben bu konuda bir blogpost yazdım. Bu yazı o serialize büyük boyutlu diziler için küçük iyi seçimdir gösterilir. Çok büyük diziler için (> 70MB) JSON daha iyi bir seçimdir.

PHP için farklı bir serileştirme 'motor' sağlayan - Ayrıca https://github.com/phadej/igbinary ilginizi çekebilir.

64bit platformu gösteri PHP 5.3.5 kullanarak benim rastgele / gelişigüzel 'performans' rakamları:

JSON:

  • JSON 2,180496931076 saniye içinde kodlanan
  • JSON 9,8368630409241 saniye içinde çözülür
  • tefrika "Dize" boyutu: 13993

Yerli PHP:

  • PHP 2,9125759601593 saniye tefrika
  • PHP 6,4348418712616 saniyede dizgilenmemiş
  • tefrika "Dize" boyutu: 20769

Igbinary:

  • 1,6099879741669 saniye tefrika WIN igbinary
  • WIN igbinrary dizgilenmemiş 4,7737920284271 saniyede
  • WIN tefrika "Dize" Boyutu: 4467

Yani, igbinary_serialize etmek daha hızlıdır () ve igbinary_unserialize () ve daha az disk alanı kullanır.

Ben yukarıdaki gibi kod fillArray (3 0) kullanılır, ama dizi anahtarları uzun dizeleri yaptı.

igbinary PHP'nin serialize olabilir (Yani nesneler vb hiçbir sorun) gibi aynı veri türlerini saklayabilir ve oturum eğer bu kadar dilek işlemek için kullanmak PHP5.3 söyleyebilirim.

Özellikle 14/15/16 slaytlar - http://ilia.ws/files/zendcon_2010_hidden_features.pdf Ayrıca bakınız

Y sadece seri ve json encode ve decode test, artı boyutu depolanan dize alacaktır.

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

Biz JSON hızlı kodlar ve bir küçük dize sonuçları, fakat dize çözmek için hızlı unserialize olduğu sonucuna varabiliriz.

Eğer sonuçta zaman içinde daha sonraki bir noktada "include" isteyeceksiniz bilgileri önbelleğe iseniz, var_export kullanarak denemek isteyebilirsiniz. Eğer sadece "unserialize" in ", tefrika" ve değil darbe vuracaktır bu şekilde.

Ben unserialization performansı dahil testi artar. İşte aldım sayılardır.

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

Yani json kodlama ama çözmede yavaş daha hızlı gibi görünüyor. Bu yüzden size en çok ne bekliyoruz uygulamanıza bağlıdır ve olabilir.

Eğer son kararınızı vermeden önce, JSON biçimi ilişkisel diziler için güvenli olmadığını unutmayın - json_decode() yerine nesneler olarak dönecektir:

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

Çıktı:

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

Ben de her türlü veri (dize, NULL, tamsayılar) ile oldukça karmaşık, hafif iç içe geçmiş çok karma üzerinde iyice bu test ve unserialize hızlı json_encode / json_decode daha sona erdi / serialize ettik.

Tek avantajı json benim testlerde bu 'dolu' boyutu daha küçük idi var.

Bunlar PHP 5.3.3 altında yapılır, daha fazla ayrıntı istiyorsanız bana bildirin.

İşte o test sonuçları bunları üretmek için kod vardır. Ben vahşi çıkmak izin veremem bilgiler ortaya ediyorum çünkü ben test verilerini sağlayamaz.

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

I made a small benchmark as well. My results were the same. But I need the decode performance. Where I noticed, like a few people above said as well, unserialize is faster than json_decode. unserialize takes roughly 60-70% of the json_decode time. So the conclusion is fairly simple: When you need performance in encoding, use json_encode, when you need performance when decoding, use unserialize. Because you can not merge the two functions you have to make a choise where you need more performance.

Pseudo benim kriter:

  • Birkaç rastgele anahtarları ve değerleri ile array $ dizi tanımlayın
  • x
  • y için < 1000; y + +; kalk zaman - json kodlanmış dize json_decode
  • y için < 1000; y + +; tefrika dize unserialize - kalk zaman
  • hızlıydı sonucu yankı

Ortalamasının üzerinde: unserialize 4 kez json_decode üzerinden 96 kez kazandı. 2.5ms üzerinde kabaca 1.5ms bir ortalamaları ile.

Serialize Ben 2 nedenlerle kullanmak için gidiyorum biri gibi görünüyor:

  • Birisi json_decode daha hızlı ve 'oku' olgu 'yazma' durumda daha olası geliyor unserialize olduğuna dikkat çekti.

  • Geçersiz UTF-8 karakterleri ile dizeleri olan zaman ben json_encode ile sorun yaşadım. Bu olduğu zaman dize bilgilerin boş kaybına neden olmak biter.

Sadece bir Bilginize - sen ama daha sıkıştırma ve daha yüksek performans ile okumak ve JSON gibi anlamak kolay şey için verileri seri etmek istiyorsanız, messagepack. kontrol etmelisiniz

Yedekleme Veri istiyorum ve farklı bir makinede veya FTP üzerinden geri eğer JSON iyidir.

Eğer bir Windows sunucu üzerinde veri depolamak Örneğin, tefrika ile, FTP üzerinden indirmek ve karakteri yeniden kodlama için daha fazla dolayı çalışmıyor olabilir bir Linux birinde geri, serialize dizeleri uzunluğu sakladığından ve Unicode > UTF-8 dönüştürme bazı 1 byte Charachter uzun algoritma kaza yapıyor 2 byte oldu olabilir.

THX - Bu kriter kodu:

My results on array I use for configuration are as fallows: JSON encoded in 0.0031511783599854 seconds
PHP serialized in 0.0037961006164551 seconds
json_encode() was roughly 20.47% faster than serialize() JSON encoded in 0.0070841312408447 seconds
PHP serialized in 0.0035839080810547 seconds
unserialize() was roughly 97.66% faster than json_encode()

So - kendi veri test.

Gerçekten konu güzel ve birkaç cevapları okuduktan sonra, ben bu konuda benim deneyler paylaşmak istiyorum.

Ben bazı "büyük" masa Ben veritabanına konuşmak hemen hemen her zaman (sadece bir gerçeği neden sormayın) sorgulanacak gereken bir kullanım dava var. Bu farklı istekleri önbelleğe olacak gibi veritabanı önbellek sistemi uygun değildir, bu yüzden hakkında olsa php önbelleğe alma sistemleri.

Ben denedim apcu ama ihtiyaçlarına uymayan, bellek bu durumda güvenilir yeterli değildir. Sonraki adım, serileştirme ile bir dosyaya önbelleğe oldu.

Tablo 18 sütun, bu tefrika önbelleği okuma benim testleri ve istatistikler vardır ile 14355 girişleri vardır:

JSON:

Tüm söylediğim gibi, birlikte büyük bir rahatsızlık json_encode / json_decode bir StdClass örneği (ya da Nesne) için her şeyi dönüştüren olmasıdır. Eğer döngü bu gerekiyorsa, bir dizi dönüştürerek muhtemelen ne yapacağız, ve evet bu dönüşüm süresini arttırmak oluyor

ortalama süresi: 780,2 ms; Bellek kullanımı: 41.5MB; önbellek dosya boyutu: 3.8MB

Msgpack

@ Baraka bahseder msgpack. Oldukça sitesi. Adlı bir deneyelim bunu vereyim?

ortalama süresi: 497 ms; Bellek kullanımı: 32MB; önbellek dosya boyutu: 2,8 MB

Bu daha iyi, ama yeni bir uzantısı gerektirir; bazen korkar insanlar derleme ...

IgBinary

@ GingerDog bahseder igbinary. Ben dosya boyutu daha performansları okuma hakkında daha fazla bakım çünkü igbinary.compact_strings=Off kurdum unutmayın.

ortalama süresi: 411.4 ms; Bellek kullanımı: 36.75MB; önbellek dosya boyutu: 3.3MB

Msg paketinden daha iyi. Yine de, bu bir çok derleme gerektirir.

serialize/unserialize

ortalama süresi: 477.2 ms; Bellek kullanımı: 36.25MB; önbellek dosya boyutu: 5.9MB

JSON daha iyi performanslar, büyük dizi yavaş json_decode zaten yeni, ama vardır.

Bu dış uzantıları dosya boyutunu daraltarak ve kağıt üzerinde harika görünüyor vardır. Sayılar * yalan söylemez. Eğer standart bir PHP fonksiyonu ile olurdu hemen hemen aynı sonuçları elde eğer bir uzantısı derleme ne anlamı var?

Biz de sizin ihtiyaçlarınıza bağlı olarak, bir başkası daha farklı bir şey tercih edeceğini anlamak olabilir:

  • IgBinary gerçekten güzel ve MsgPack daha iyi yapar
  • Msgpack is better at compressing your datas (note that I didn't tried the igbinary compact.string option).
  • Derlemek istemiyor musunuz? Standartlarını kullanın.

İşte bu, size birini seçmenize yardımcı olmak için başka bir serileştirme yöntemleri karşılaştırma!

Sadece standart hardrive ve eski çift çekirdekli işlemci ile çözme - - senin istatistikleri farklı olabilir 10 aynı kullanım durumunda testler, ortalama sayılar * PHPUnit 3.7.31, php 5.5.10 ile test edilmiştir