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


609

Önbellek amacıyla düz bir dosyada çok boyutlu ilişkisel bir dizi veri depolamak gerekir. Bazen web uygulamamda kullanmak için JSON'a dönüştürme ihtiyacına rastlayabilirim ama zamanın büyük çoğunluğu doğrudan PHP'de diziyi kullanacağım.

Diziyi bu metin dosyasında JSON veya PHP serileştirilmiş dizi olarak depolamak daha verimli olur mu? Etrafa baktım ve PHP'nin (5.3) en yeni sürümlerinde json_decode, aslında daha hızlıunserialize .

Şu anda JSON olarak dizi depolamaya doğru eğildim, çünkü gerekirse bir insan tarafından okunması daha kolay, PHP ve JavaScript'te çok az çaba ile kullanılabilir ve okuduğumdan, hatta daha hızlı kod çözme (kodlama konusunda emin değilim).

Herhangi bir tuzak bilen var mı? Herhangi bir yöntemin performans faydalarını göstermek için iyi kriterler var mı?

Yanıtlar:


563

Önceliklerinize bağlıdır.

Performans mutlak sürüş özelliğinizse, elbette en hızlı olanı kullanın. Bir seçim yapmadan önce farklılıkları tam olarak anladığınızdan emin olun.

  • Bunun aksine, serialize()UTF-8 karakterlerine dokunmamak için ekstra parametre eklemeniz gerekir: json_encode($array, JSON_UNESCAPED_UNICODE) (aksi takdirde UTF-8 karakterlerini Unicode kaçış dizilerine dönüştürür).
  • JSON nesnenin orijinal sınıfının ne olduğunu hatırlamaz (her zaman stdClass örnekleri olarak geri yüklenir).
  • JSON ile __sleep()ve kaldıraçtan yararlanamazsınız__wakeup()
  • Varsayılan olarak, yalnızca ortak mülkler JSON ile serileştirilir. ( bu davranışı değiştirmek için JsonSerializablePHP>=5.4 uygulayabilirsiniz ).
  • JSON daha taşınabilir

Ve muhtemelen şu anda düşünemediğim birkaç fark var.

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

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

31
"JSON UTF-8 karakterlerini unicode kaçış dizilerine dönüştürür." Artık mutlaka doğru değil: Artık var JSON_UNESCAPED_UNICODE.
TRiG

32
İşte neredeyse 5 yıl sonra ve testleri tekrar yaptım (sadece json_encode) ve şimdi serileştirmekten ortalama% 131 daha hızlı. Bu nedenle, 5.3.x üzerinde 5.4.x sürümünde bu fonksiyonda bazı güzel iyileştirmeler yapılmalıdır. Özellikle, CentOS 6 5.4.24 çalıştırıyorum. Yani, JSON için yay !!
KyleFarris

8
benim durumumda bir kez kodlamak ve çok deşifre biz unserialize vs json_decode benchmarked ve sonuçları JSON ,093269109725952 saniyelik <br> json_decode içinde Dizgeleşmiş nesnenin yeniden ,06662392616272 saniyelik <br> PHP'de dcoded oldu () kabaca 39,99% unserialize daha hızlıydı ()
AMB

21
İlginç: Bu kodu 3v4l.org'da çalıştırırsanız , en son PHP7 geliştirme derlemeleri json_encode'dan daha hızlı seri hale gelir: "serialize () json_encode () 'den kabaca%
76.53

21
2017, PHP 7.1 veserialize() was roughly 35.04% faster than json_encode()
Elias Soares

239

JSON PHP'nin seri hale biçiminden daha basit ve daha hızlıdır ve kullanılması gerektiğini sürece :

  • Derin iç içe diziler saklıyorsunuz json_decode():: "JSON kodlu veriler 127 öğeden daha derinse, bu işlev false değerini döndürür."
  • Doğru sınıf olarak serileştirilmesi gereken nesneleri saklıyorsunuz
  • Json_decode'u desteklemeyen eski PHP sürümleriyle etkileşime giriyorsunuz

12
Mükemmel cevap. Haha, 127 seviyeli derin bir delilik gibi görünüyor; Neyse ki en fazla 2-3 gibi gidiyorum. Json_decode / json_encode'un serileştirmeden / serileştirmeden daha hızlı olduğu gerçeğini yedekleyecek verileriniz var mı?
KyleFarris

1
Bir süre önce test ettim ve json daha hızlı çıktı - veriye artık sahip değilim.
Greg

47
"5.3.0 İsteğe bağlı derinlik eklendi. Varsayılan özyineleme derinliği 128'den 512'ye yükseltildi"
giorgio79

4
Yukarıdaki listeye bir öğe daha eklemek istiyorum: verileriniz geçersiz UTF-8 bayt dizileri içeriyorsa, json_encode () kullanılmamalıdır. Bu tür veriler için sadece false değerini döndürür. Örneğin şunu deneyin: var_dump (json_encode ("\ xEF \ xEF"));
pako

2
Genel olarak daha hızlı olduğu doğru değil. Yaklaşık ~ 500 giriş içeren küçük bir diziniz varsa, dizileştirme / serileştirme aslında% 200-400 daha hızlıdır, json_decode / json_encode (PHP 5.6.19)
Adam

59

Bu konuyla ilgili bir blog yazısı yazdım: " Büyük bir diziyi önbelleğe al: JSON, serialize veya var_export? " . Bu yazıda, serileştirmenin küçük ve büyük boyutlu diziler için en iyi seçim olduğu gösterilmiştir. Çok büyük diziler için (> 70MB) JSON daha iyi bir seçimdir.


8
Bağlantı artık mevcut değil.
Martin Thoma

1
Teşekkürler, geyik, bağlantıyı güncelledim. Makale neredeyse 6 yaşında olmasına rağmen ve mevcut PHP sürümleri için bu kadar doğru olmayabilir.
Taco

Bazı testler yaptım ve test etmek için basit bir işlev yaptım, büyük dizilerle (Peter Bailey'in bu işlevi kullananlar için) json_encode()yaklaşık % 80 ila% 150 daha hızlıdır (gerçekten orada yukarı ve aşağı gidiyor) serialize(), yaklaşık 300 yineleme ile. Ancak daha küçük dizileri ( array("teams" => array(1 => array(4 arrays of players), 2 => array(4 arrays of players)))) kullanırken, 750.000 yineleme ile test yaptım ve bu serialize()durumda yaklaşık % 6 ila% 10 daha hızlı. İşlevim tüm yinelemeler için ortalama süreleri alır ve karşılaştırır. Buraya bir cevap olarak gönderebilirim
MiChAeLoKGB

veriler sadece PHP tarafından kullanılıyorsa, var_export benim işim. Sadece içerme düşüncesindeki olası sözdizimi hatalarına dikkat etmelisiniz.
Gfra54

3
blog artık mevcut değil
popeye

53

Ayrıca , PHP için farklı bir serileştirme 'motoru' sağlayan https://github.com/phadej/igbinary ile de ilgilenebilirsiniz .

64bit platformda PHP 5.3.5 kullanan rastgele / rastgele 'performans' rakamlarım:

JSON:

  • JSON 2.180496931076 saniyede kodlanmış
  • JSON 9.8368630409241 saniyede çözüldü
  • serileştirilmiş "Dize" boyutu: 13993

Yerel PHP:

  • PHP 2.9125759601593 saniyede serileştirildi
  • PHP 6.4348418712616 saniyede serileştirilmemiş
  • serileştirilmiş "Dize" boyutu: 20769

İkili:

  • WIN igbinary 1.6099879741669 saniyede seri hale getirildi
  • WIN igbinrary 4.7737920284271 saniyede diziselleştirilmemiş
  • WIN serileştirilmiş "String" Boyutu: 4467

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

Yukarıdaki gibi fillArray (0, 3) kodunu kullandım, ancak dizi anahtarlarını daha uzun dizeler yaptım.

igbinary, PHP'nin yerel serileştirmesi ile aynı veri türlerini saklayabilir (yani nesnelerle ilgili bir sorun yok vb.) ve isterseniz PHP5.3'e oturum işleme için kullanmasını söyleyebilirsiniz.

Ayrıca bkz http://ilia.ws/files/zendcon_2010_hidden_features.pdf - özellikle slaytlar 14/15/16


25

Y sadece serileştirilmiş ve json kodlama ve kod çözme, artı boyutu saklanan dize alacak test.

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

JSON'un daha hızlı kodladığı ve daha küçük bir dize oluşturduğu sonucuna varabiliriz, ancak diziselleştirmenin dizeyi deşifre etmesi daha hızlıdır.


6
İnsanların neden bu kadar küçük veri kümesiyle performans testi yaptığını bilmiyorum. Sonuçlarınıza hata ekleyen tüm ek yüke sahip olmak. Ve insanlar performansla ilgileniyorsa, muhtemelen çok büyük bir veri kümesine sahip oldukları için, çünkü bir kez mikro sn kazanmanın bir anlamı yoktur.
Yann Sagon

1
Çoğu zaman birçok küçük veri setini yineliyorum. Yüzlerce küçük veri kümesiyle, her biri için 1mS kazanmak hala ilginç.
Teson

@YannSagon Küçük veri kümelerinde bile bir performans testi yapmak mantıklıdır. Testten önce sadece bir mikro saniye olup olmadığını nasıl anlamanız gerekir?
Adam


12

Serileştirme performansını dahil etmek için testi artırdım. İşte aldığım sayılar.

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

Dolayısıyla json kodlama için daha hızlı, ancak kod çözmede yavaş görünüyor. Bu, uygulamanıza ve en çok ne yapmayı beklediğinize bağlı olabilir.


9

Gerçekten güzel bir konu ve birkaç cevabı okuduktan sonra konuyla ilgili deneylerimi paylaşmak istiyorum.

Bazı "büyük" tablo hemen hemen her veritabanında sorgulanması gereken bir kullanım durumu var (neden sorma, sadece bir gerçek). Veritabanı önbellekleme sistemi farklı istekleri önbellek olmaz gibi uygun değil, bu yüzden php önbellek sistemleri hakkında olsa.

Denedim apcuama ihtiyaçlara uymadı, bu durumda bellek yeterince güvenilir değil. Bir sonraki adım, serileştirme ile bir dosyaya önbellek oluşturmaktı.

Tabloda 18 sütun içeren 14355 giriş var, bunlar benim testlerim ve serileştirilmiş önbelleği okuma istatistikleri:

JSON:

Hepinizin söylediği gibi, json_encode/ ile ilgili en büyük sıkıntı, json_decodeher şeyi bir StdClassörneğe (veya Nesneye) dönüştürmesidir. Döngüye ihtiyacınız varsa, bir diziye dönüştürmek muhtemelen yapacağınız şeydir ve evet dönüşüm süresini uzatıyor

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

Msgpack

@hutch söz msgpack . Güzel bir web sitesi. Bir deneyelim, olur mu?

ortalama süre: 497 ms; bellek kullanımı: 32MB; önbellek dosya boyutu: 2.8MB

Bu daha iyi, ancak yeni bir uzantı gerektiriyor; bazen korkan insanları derlemek ...

IgBinary

@GingerDog söz igbinary . Ayarladığımı unutmayın igbinary.compact_strings=Offçünkü okuma performanslarını dosya boyutundan çok önemsiyorum.

ortalama süre: 411,4 ms; bellek kullanımı: 36.75MB; önbellek dosya boyutu: 3.3MB

Msg paketinden daha iyi. Yine de, bu da derleme gerektirir.

serialize/unserialize

ortalama süre: 477,2 ms; bellek kullanımı: 36.25MB; önbellek dosya boyutu: 5.9MB

JSON'dan daha iyi performanslar, dizi ne kadar büyükse, o kadar yavaştır json_decode, ama siz zaten yenisiniz.

Bu harici uzantılar dosya boyutunu daraltıyor ve kağıt üzerinde harika görünüyor. Sayılar yalan söylemez *. Standart bir PHP işleviyle neredeyse aynı sonuçları alırsanız bir uzantıyı derlemenin anlamı nedir?

Ayrıca, ihtiyaçlarınıza bağlı olarak, başka birinden farklı bir şey seçeceğinizi çıkarabiliriz:

  • IgBinary gerçekten güzel ve MsgPack'ten daha iyi performans gösteriyor
  • Msgpack, verilerinizi sıkıştırmakta daha iyidir (igbinary compact.string seçeneğini denemediğimi unutmayın).
  • Derlemek istemiyor musunuz? Kullanım standartları.

İşte bu, birini seçmenize yardımcı olacak başka bir serileştirme yöntemi karşılaştırması!

* PHPUnit 3.7.31, php 5.5.10 ile test edildi - sadece standart bir hardrive ve eski çift çekirdekli CPU ile kod çözme - 10 aynı kullanım senaryosu testindeki ortalama sayılar, istatistikleriniz farklı olabilir


Neden dizileri döndürmeyi zorlamak için json_decode'a iletilmiyor?
Alex Yaroshevich

Çünkü yavaş. Ben bunu test etmedi ama sadece php tür değişikliği zorlamak daha hızlı olduğunu düşünüyorum.
soyuka

Ben sadece php nesnelerden daha hızlı diziler oluşturma biliyorum.
Alex Yaroshevich

Yani json_decode($object, true), hakkında konuşuyorsunuz , temel olarak aynı (array) json_decode($object)ama yinelemeli olarak yapılacak, böylece aynı davranış olacak ve her iki durumda da önemli bir maliyeti olacaktır. Unutmayın ki performans farkları arasında test yapmadım StdClassve arraybu gerçekten önemli değil.
soyuka

Eminim bu başka bir maliyet çünkü nesneler olmadan daha düşük seviyede yapılır.
Alex Yaroshevich

8

Serileştirmek 2 nedenden dolayı kullanacağım gibi görünüyor:

  • Birisi, serileştirmenin json_decode'dan daha hızlı olduğuna dikkat çekti ve bir 'okuma' vakası 'yazma' vakasından daha muhtemel görünüyor.

  • Geçersiz UTF-8 karakterli dizeler yaparken json_encode ile sorun yaşadım. Bu durumda dize boş kalır ve bilgi kaybına neden olur.


Lütfen son noktanızı bir örnekle
açıklayabilir misiniz

6

Bu çok karmaşık, hafif iç içe çok karma (her türlü veri (dize, NULL, tamsayılar) ile test ettik ve serialize / unserialize json_encode / json_decode çok daha hızlı sona erdi.

Json'un testlerimdeki tek avantajı daha küçük 'paketlenmiş' boyutta olmasıydı.

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

İşte test sonuçları daha sonra bunları üretmek için kod. Test verilerini veremiyorum çünkü vahşi doğada dışarı çıkamayacağım bilgileri ortaya koyuyor.

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

PHP 5.4.12 ile benzer bir test yaptım ve benzer sonuçlar buldum: {un,} serialize daha hızlı. Verilerim 3 seviye derinliğinde (900k serileştirilmiş) hash değerleridir.
sorpigal

6

Ben de küçük bir kıyaslama yaptım. Sonuçlarım aynıydı. Ama kod çözme performansına ihtiyacım var. Yukarıda fark ettiğim birkaç kişi gibi fark ettiğim yerden unserializedaha hızlı json_decode. zamanın unserializeyaklaşık% 60-70'ini alır json_decode. Sonuç olarak oldukça basittir: Kodlamada json_encodeperformansa ihtiyacınız olduğunda, kod çözme sırasında performansa ihtiyacınız olduğunda kullanın unserialize. Çünkü iki işlevi birleştiremezsiniz, daha fazla performansa ihtiyaç duyduğunuz yerde bir seçim yapmanız gerekir.

Sözde benim kriter:

  • $ Arr dizisini birkaç rastgele anahtar ve değerle tanımlayın
  • x <100 için; x ++; serialr ve json_encode $ dizi
  • y <1000 için; y ++; json_decode json kodlanmış dize - hesap süresi
  • y <1000 için; y ++; serileştirilmiş dizgenin serileştirilmesi - calc time
  • daha hızlı sonucu yankılamak

Ortalamada: unserialize, json_decode'un 4 katında 96 kez kazandı. 2.5ms üzerinde yaklaşık 1.5ms bir ortalama ile.


3

Son kararınızı vermeden önce, JSON biçiminin ilişkilendirilebilir diziler için güvenli olmadığını unutmayın json_decode(); bunun yerine bunları nesne olarak döndürür:

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

Gerçekten, haklısın. Ben, demek olan JavaScript nesne afterall notasyonu! Neyse ki, eğer biliyor kullanmakta kodlanmış şey bu json_encodeoldu bir ilişkisel dizi, kolayca geri şöyle bir dizi içerisine zorlayabilirsiniz: $json = json_encode($some_assoc_array); $back_to_array = (array)json_decode($json);erişim böylece tipik bir senaryoda PHP'de diziler aynı şekilde nesneleri yapabilirsiniz o nota 's iyi Ayrıca farkı bile bilmiyordu. Gerçi iyi bir nokta!
KyleFarris

30
@toomuchphp, üzgünüm ama yanılıyorsun. Json_decode için 'bool $ assoc = false' için ikinci bir parametre vardır, bu da json_decode'un bir dizi üretmesini sağlar. @KyleFarris, bu aynı zamanda typecast'i diziye kullanmaktan daha hızlı olmalıdır.
janpio

cevap doğru değil. true işlevinin ikinci parametresi olarak kullanıldığında, json_decode () nesneler yerine ilişkilendirilebilir diziler döndürür.
Marvin Saldinger

3

İlk olarak, senaryoyu biraz daha kıyaslama yapmak için değiştirdim (ve sadece 1 yerine 1000 çalıştırma yaptım):

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

PHP 7'nin bu yapısını kullandım:

PHP 7.0.14 (cli) (yerleşik: 18 Ocak 2017 19:13:23) (NTS) Telif Hakkı (c) 1997-2016 PHP Grubu Zend Motoru v3.0.0, Telif Hakkı (c) 1998-2016 Zend OPcache ile Zend Technologies v7.0.14, Telif Hakkı (c) 1999-2016, Zend Technologies

Ve sonuçlarım:

serialize () (kazanç: 999) json_encode () 'dan kabaca% 10.98 daha hızlı idi ()

Yani açıkça , serialize / unserialize olduğu en hızlı json_encode / kod çözme iken, yöntem en taşınabilir.

Serileştirilmiş verileri PHP olmayan bir sisteme göndermeniz veya almanız gerektiğinden 10x veya daha sık okuduğunuz / yazdığınız bir senaryoyu düşünüyorsanız, serileştirme / diziselleştirmeyi kullanmak ve serileştirmeden önce json_encode veya json_decode kullanmanız daha iyi olur zaman açısından.


2

Sonuçları buradan kontrol edin (PHP kodunu JS kod kutusuna koyarak kesmek için üzgünüm):

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

BULGULAR: serialize()ve unserialize()her ikisi de PHP 5.4'te değişen büyüklükteki dizilerde önemli ölçüde daha hızlıdır.

Json_encode vs serialize ve json_decode vs unserialize karşılaştırmak için gerçek dünya verileri üzerinde bir test komut dosyası yaptım. Test, bir üretim e-ticaret sitesinin önbellekleme sistemi üzerinde gerçekleştirildi. Sadece önbellekteki verileri alır ve tüm verileri kodlamak / kodunu çözmek (veya serileştirmek / serileştirmek) için zamanları test eder ve bunu görmek kolay bir tabloya koyarım.

Ben PHP 5.4 paylaşılan barındırma sunucusunda koştu.

Sonuçlar, büyük ve küçük veri setlerinin serileştirilmesi ve serileştirilmemesi açısından açık kazananlar olduğu sonucuna vardı. Özellikle benim kullanım durumum için, json_decode ve unserialize önbellekleme sistemi için en önemlisidir. Serileştirme burada neredeyse her yerde kazanan oldu. Genellikle json_decode'dan 2 ila 4 kat (bazen 6 veya 7 kat) daha hızlıdır.

@ Peter-bailey'deki sonuçlardaki farkı not etmek ilginçtir.

Sonuçları oluşturmak için kullanılan PHP kodu şöyledir:

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

1

sadece bir fyi - verilerinizi JSON gibi okunması ve anlaşılması kolay bir şeye serileştirmek istiyorsanız, ancak daha fazla sıkıştırma ve daha yüksek performansla, mesaj paketini kontrol etmelisiniz.


2
eğer sadece bir fyi ise, bir yorum olarak koysan iyi olur.
technophyle

0

Verileri yedeklemek ve farklı bir makinede veya FTP üzerinden geri yüklemek istiyorsanız JSON daha iyidir.

Örneğin, bir Windows sunucusunda veri depolarsanız, FTP yoluyla indirir ve daha sonra yeniden karakter kodlaması nedeniyle çalışamayacağı bir Linux sunucusuna geri yüklerseniz serileştirme ile, serialize dizelerin uzunluğunu ve Unicode'da depolar. > 1 baytlık karakter kodlaması UTF-8 kodlaması 2 bayt uzunluğunda olabilir ve algoritma çökmesine neden olabilir.


0

THX - bu karşılaştırma kodu için:

Yapılandırma için dizi Ben kullanımına Benim sonuçları Taksonların gibidir: JSON ,0031511783599854 saniyede kodlanmış
PHP 0,0037961006164551 saniyede tefrika
json_encode()daha hızlı kabaca% 20.47 oldu serialize() JSON 0,0070841312408447 saniyede kodlanmış
PHP 0,0035839080810547 saniye tefrika
unserialize()edilmiş kabaca% 97.66 daha hızlıjson_encode()

Yani - kendi verilerinizde test edin.


Yani "unserialize () içindeki json_decode (), json_encode ()" 'dan kabaca% 97.66 daha hızlıydı, evet?
Meezaan-ud-Din

0

İnsanların burada söylediklerini özetlemek gerekirse, json_decode / encode serileştirmek / serileştirmekten daha hızlı görünüyor, ancak var_dump yaparsanız serileştirilmiş nesnenin türü değiştirilir. Herhangi bir nedenle türü tutmak istiyorsanız, seri hale getirin!

(örneğin stdClass ve diziyi deneyin)

serialize / unserialize:

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 kodlama / kod çözme

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]

Gördüğünüz gibi json_encode / decode hepsini stdClass'a dönüştürüyor, ki bu iyi değil, nesne bilgisi kayboldu ... Yani sadece diziler değilse, ihtiyaçlara göre karar verin ...


Sadece bir not: Diğer cevapların çoğu seri hale getirme / seriyi kaldırma işleminin daha hızlı olduğunu söylüyor.
Ecker00

-3

json_encodeVeya kullanmayacak bir dosya önbellek mekanizması olan Süper Önbellek kullanmanızı öneririm serialize. Diğer PHP Önbellek mekanizmasına kıyasla kullanımı basit ve gerçekten hızlı.

https://packagist.org/packages/smart-php/super-cache

Ör:

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

-1. Daha iyi bir çözüm olsa da, bu cevabın hiçbir kısmı OP'nin sorusunu cevaplamıyor. Gelecekte, belki de soruyu cevaplamayı deneyin, ancak alternatif bir çözümün araştırılmaya değer olabileceği yönünde bir öneri bırakın.
starbeamrainbowlabs
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.