PHP geniş bir dizi serialize?

13 Cevap php

Ben merak ediyorum, PHP, tefrika bir boyut sınırı vardır. O bir önbellek içine saklanabilir böylece 5000 anahtarları ve değerleri ile bir dizi seri hale getirmek mümkün olabilir mi?

Ben bir sosyal ağ sitesinde bir kullanıcıların arkadaş listesi önbelleğe umuyorum, önbellek oldukça sık güncellenen gerekir ama neredeyse her sayfası yükleme okumak gerekir.

Tek bir sunucu kurulumu ben APC, bu için memcache sonra daha iyi olacağını varsayarak yaşıyorum.

13 Cevap

Oldukça birkaç kişi zaten cevap olarak, sadece eğlence için, burada (do I dare calling it that ? ) çok hızlı bir kriter bulunuyor; Aşağıdaki kodu göz önünde bulundurun:

$num = 1;

$list = array_fill(0, 5000, str_repeat('1234567890', $num));

$before = microtime(true);
for ($i=0 ; $i<10000 ; $i++) {
    $str = serialize($list);
}
$after = microtime(true);

var_dump($after-$before);
var_dump(memory_get_peak_usage());

I'm running this on PHP 5.2.6 (the one bundled with Ubuntu jaunty).
And, yes, there are only values ; no keys ; and the values are quite simple : no object, no sub-array, no nothing but string.

$num = 1, olsun için:

float(11.8147978783)
int(1702688)

$num = 10, olsun için:

float(13.1230671406)
int(2612104)

Ve, için $num = 100, olsun:

float(63.2925770283)
int(11621760)

Yani, dizinin her bir elemanı uzun sürer (seems fair, actually), bir büyük görünüyor. Ancak, 100 kat daha büyük elemanlar için, çok daha uzun 100 kez yapmayız ...


Now, with an array of 50000 elements, instead of 5000, which means this part of the code is changed :

$list = array_fill(0, 50000, str_repeat('1234567890', $num));

$num = 1 ile, olsun:

float(158.236332178)
int(15750752)

O 1 için aldı süresini göz önüne alındığında, ben $ = 10 num ne $ num = 100 ya bu koşma olmayacak ...


Yes, of course, in a real situation, you wouldn't be doing this 10000 times ; so let's try with only 10 iterations of the for loop.

Için $num = 1,

float(0.206310987473)
int(15750752)

Için $num = 10,

float(0.272629022598)
int(24849832)

Ve için $num = 100,

float(0.895547151566)
int(114949792)

Yeah, that's almost 1 second -- and quite a bit of memory used ^^
*(No, this is not a production server : I have a pretty high memory_limit on this development machine ^^ )*


So, in the end, to be a bit shorter than those number -- and, yes, you can have numbers say whatever you want them to -- I wouldn't say there is a "limit" as in "hardcoded" in PHP, but you'll end up facing one of those :

  • max_execution_time (genellikle, bir web sunucusu üzerinde, bu 30 saniyeden daha fazla asla)
  • memory_limit (bir web sunucusu üzerine, bu genellikle 32MB fazla muco değil)
  • Sen sunucusu yük olacak: bu büyük serialize-döngü 1 çalışırken, benim CPU 1 aldı; Eğer aynı anda aynı sayfada kullanıcıların oldukça bir çift olan varsa, ben bunu verecek ne hayal edelim ;-)
  • Lütfen kullanıcı sabır ^ ^

But, except if you are really serializing long arrays of big data, I am not sure it will matter that much...
And you must take into consideration the amount of time/CPU-load using that cache might help you gain ;-)

Yine de bilmek en iyi yolu gerçek veriler ile, kendiniz test olacağını ;-)


And you might also want to take a look at what Xdebug can do when it comes to profiling : this kind of situation is one of those it is useful for!

serialize() fonksiyonu sadece bellek ile sınırlıdır.

Serileştirme bellekte bir dize oluşturma içerir beri yalnızca pratik limiti, kullanılabilir bellek.

PHP tarafından uygulanan sınır yoktur. Serialize tefrika yapısı bir bayt akışı gösterimini (dize) döndürür, böylece sadece büyük bir dize almak istiyorum.

Yukarıda Thinker tarafından önerilen:

Sen kullanabilirsiniz

$string = json_encode($your_array_here);

ve kodunu çözmek

$array = json_decode($your_array_here, true);

Bu bir dizi döndürür. Bu kodlanmış dizi çok katlı olsa bile iyi çalışır.

Tamam ... daha fazla sayı! (PHP OSX, hiçbir opcode önbellek 5.3.0)

10k iters de n = 1 için benim makinede @ Pascal'ın kod üretir:

float(18.884856939316)
int(1075900)

Ben kadar yukarıda () unserialize ekleyin.

$num = 1;

$list = array_fill(0, 5000, str_repeat('1234567890', $num));

$before = microtime(true);
for ($i=0 ; $i<10000 ; $i++) {
    $str = serialize($list);
    $list = unserialize($str);
}
$after = microtime(true);

var_dump($after-$before);
var_dump(memory_get_peak_usage());

üretir

float(50.204112052917)
int(1606768)

Ben fazladan 600K kabul ya da öylesine tefrika dize vardır.

Ben orijinal üretir içinde) (yerine, tefrika ve var_export ve include / eval ortağı $str = var_export($list, true); merak ediyordum

float(57.064643859863)
int(1066440)

(en azından bu basit örneğin) bu yüzden sadece biraz daha az bellek ama şimdiden yolu daha fazla zaman.

Yukarıda yerine unserialize içinde eval('$list = '.$str.';'); ekleyerek üretir

float(126.62566018105)
int(2944144)

Eval :-/ yaparken yere theres muhtemelen bir bellek sızıntısı göstermektedir.

Yani yine, bu büyük kriterler değildir (ben gerçekten yerel var falan dize koyarak eval / unserialize izole etmeliyiz, ama tembel oluyorum) ama onlar ilgili eğilimleri gösterir. var_export yavaş görünüyor.

Hayır, hiçbir sınır ve bu var:

set_time_limit(0);
ini_set('memory_limit ', -1);

unserialize('s:2000000000:"a";');

you should have safe.mode = On or a extension like Suhosin installed, aksi takdirde sistem içinde tüm bellek yiyiyor nedeni budur.

I better than serialize is json_encode function. Bu bir dezavantajı var, o birleşmeli diziler ve nesneler ayırt değildir düşünüyorum, ama dize sonuç daha küçük ve insan tarafından okunması daha kolaydır, bu yüzden de hata ayıklama ve düzenlemek için.

Bunu önbelleğe istiyorsanız (yani performans sorunu olduğunu varsayalım), bellekte bir dize + kazanç önbellek onu dönüştürme başarımdan önlemek yerine apc_add kullanın.

Sadece boyutu sınırı Yukarıda belirtildiği gibi kullanılabilir bellektir.

A few other gotchas: serialize'd data is not portable between multi-byte and single-byte character encodings. PHP5 classes include NUL bytes that can cause havoc with code that doesn't expect them.

Bunu yapmak için bir veritabanı kullanarak yerine PHP'nin mevcut kaynaklara güvenmek daha iyiyiz gibi kullanma durumu geliyor. MySQL gibi bir şey kullanarak avantajları bunun yerine özellikle depolama ve arama gibi işlemler için akılda bellek yönetimi ile tasarlanmış olmasıdır.

Bu gerçekten hiç eğlenceli sürekli serializing oluyor ve unserializing veri sadece bilgi birkaç parça güncellemek veya değiştirmek için.

i unserialize büyük bir tefrika bir nesne, boyut, bir istisna atar hangi bir durum var: 65535 (sihirli sayı: 16bit tam bit = 65536)

Sadece ben serileştirme bir üst limit isabet düşündüm bir örneğine rastlamak ettik.

Ben mysql TEXT alanı kullanarak bir veritabanına serileştirilmiş nesneleri ısrar ediyorum.

Bir tek baytlık karakterler için kullanılabilir karakter limiti 65.535 yüzden onlar TEXT alanının sınırı ile kesiliyor gibi onları nesneleştirmek imkansız PHP ile çok daha büyük nesneleri serialize ederken.