2010-09-07 5 views
5

Arka plan: Her Apache isteği için PHP'de belleğe yüklemem gereken büyük bir 2B dizi tam sayı var. Daha az bellek almasını istiyorum.PHP'de kısa girişler (16 bit) kullanmak mümkün mü?

PHP, çoğu sistemde 32 bit olan PHP_INT_SIZE baytlık depoları depolar. Tüm tamsayılar 2^16'dan küçüktür, yani short int (örneğin C) olabilir. Mürekkepleri kısa olarak saklamanın RAM'in yarısını alacağını düşünerek haklı mıyım?

İdeal yapabilmek istiyorum:

$s = (short) 1234; // takes up 2 bytes instead of 4 

diğer bilgiler:

  • dizi RAM 100mb hakkında kaplıyor ve
  • dökümü var_export() bir 30MB dahil edilerek oluşturulan
  • Dizi, bir cron işleminde yazılmıştır. Sadece okuma, bellek etkin (ve hızlı) olmalıdır
  • Tamsayılar üzerinde yapmam gereken tek işlem hepsini karşılaştırıyor (<,>, ===) ve daha sonra bunlardan birkaçını okuyor. Floyd-Warshall algorithm)
  • bir DB'den her değer okuma milyon birkaç yüz istek başına okur

Bazı çılgın fikirler olduğu gibi yol çok yavaş: Kullan pack()/unpack()

  • ama bu, bunu yine mağaza 32 bi olarak değerleri Onlar bir görüntüdeki piksel olarak
  • depola değerlerini çözdükten ve onları okumak için PHP'nin GD library kullanmak edildi t ints
  • kullanın shmop_read() (bu yavaş olacaktır) ve Apache süreçler dizisini paylaşan var
  • Memcached işe yarayabilecek ama onunla hiçbir deneyime sahip ve bunu
  • yeniden derleyin PHP bir doğal PHP dizinin kat kat daha yavaş
  • C öğrenin olmak ++ ve bir PHP uzantısı yazardı sanırım (ya HipHop?) ints
  • kullanımı için 2 byte kullanarak Igbinary (kullanışlıdır, ancak paket() ile aynı problemi olacaktır)
+0

kesinlikle shmop_ * işlevlerini kullanın ... bunun dışında BarsMonster ile aynı şeyi düşünebileceğimden başka. –

+1

Mysql ve bellek tablolarını kullanamadığınızdan emin misiniz? Belki de php –

+0

serileştirme ile seri veri göndermeyi önlemek için sorgu formundaki karşılaştırmaları bile yazabilir ve seri hale getirilmemiş var_export'dan daha hızlıdır, btw – raveren

cevap

4

Son yaklaşımı tavsiye etmem. :-)

hızlı çözüm için, ben bu kullanarak 1 PHP tamsayı 2 sizin tamsayılar paketi olacaktır:

Ayrıca
$big = $int1 + ($int2<<16); 

And uppack as: 

$int1 = $big & 65535; 
$int2 = ($big>>16) & 65535; 

, BÜYÜK başparmak yukarı paylaşılan hafızayı kullanma. Bu, APP yolunuzu daha hızlı hale getirecektir.

+0

Güzel bir çözüm gibi görünüyor. Tamsayılar rastgele erişilebilmeli, böylece bununla bir miktar CPU yükü olabilir, ancak eğer çalışırsa, hafıza tasarrufları buna değer olmalıdır. Ben bir ... – dave1010

2

Bu, PHP'nin tasarlandığı bir görev değil.

Verileri bellekteki verilere sahip bir uygulama yazmanızı öneririm ve hesaplamaları yapar ve sonuçları elde etmek için PHP ile arabirim oluşturur.

PHP'nin tamsayı boyutu aslında 64 bit Unix benzeri platformlarda 64 bittir.

Paylaşılan bellek çok iyi bir seçenek değil, çünkü verileri hala PHP'nin bellek alanına kopyalamanız gerekiyor.

Her şeyi bellekte tutan ve buna doğrudan erişen bir uzantı yazmak mümkündür ancak çok pratik değildir, çünkü genellikle birkaç PHP işlemi çalıştırdığınız için paylaşılan belleği (veya başka bir IPC mekanizmasını) kullanmanız gerekir.

+0

PHP ile arayüzler bir şey yazmak istiyorum, ama nereden başlayacağımı bilmiyorum. Herhangi bir işaretçi? – dave1010

+1

Soketleri veya bir çeşit [mesaj iletimi] kullanabilirsiniz (http://en.wikipedia.org/wiki/Message_passing). Java için, [PHP/Java köprüsü] 'ni kullanabilirsiniz (http://php-java-bridge.sourceforge.net/). – Artefacto

+0

Teşekkürler. Dizinin sadece bir kısmının bir seferde PHP'nin bellek alanında olması gerekiyordu, bu yüzden shmop işlevlerinin * çalışabileceğini düşünüyorum *. Hafızayı paylaşmak, daha iyi ölçekleneceği için ideal çözüm olacaktır. – dave1010

1

i oluşturmak ve ikili paketlenmiş biçimde dizi depolamak ve ArrayAccess uygulayan bir sınıf yazarak bunu meraklısı yapabilirsiniz sen onlara

function elem($n) { 
    global $buf; 
    return (ord($buf[$n << 1]) << 8) | ord($buf[$n << 1 | 1]); 
} 

$buf = file_get_contents(binary file generated by cron); 
if(elem(2) > elem(10))..... 

yalnızca gereksinim duyduğunuzda numaralar elde ediyorum sadece can böylece kodun geri kalanında elem (x) yerine myPackedArray [x] 'ı kullanın.