2010-09-07 11 views
5

Tło: Mam duży 2D tablicę liczb całkowitych, które muszę załadować do pamięci w PHP Apache dla każdego żądania. Chcę, żeby zajmowało to mniej pamięci.Czy można używać krótkich intów (16-bitowych) w PHP?

sklepy PHP INTS w PHP_INT_SIZE bajtów, która wynosi 32 bitów na większości systemów. Wszystkie liczby całkowite są mniejsze niż 2^16, co oznacza, że ​​mogą być short int (np. W C). Czy mam rację sądząc, że przechowywanie int jako krótkich zajmie połowę RAM?

Idealnie chciałabym móc zrobić:

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

Więcej informacji:

  • Tablica zajmuje około 100 MB pamięci RAM i jest generowany przez włączenie 30MB var_export() zrzucić
  • Tablica jest napisana w procesie cron. Tylko odczyt musi być pamięć efektywny (i szybki)
  • Jedyne operacje muszę zrobić na całkowite porównujemy wszystkie z nich (<,> ===), a następnie przeczytaniu kilku z nich (podobnie jak Floyd-Warshall algorithm)
  • Reading każdej wartości z DB jest zbyt powolny, jak istnieje kilka milionów odsłon na życzenie

Niektóre szalone pomysły:

  • Korzystając pack()/unpack() ale nadal sklep wartości jako 32 bi t ints kiedy zostały rozpakowane
  • przechowywać jako wartości pikseli w obrazie i używają PHP GD library je czytać (będzie to powolny)
  • Zastosowanie shmop_read() i mają procesy Apache podziel tablicę
  • Memcached może działać, ale nie mam doświadczenia z nim i myślę, że byłoby to wiele razy wolniejsze niż native tablicy PHP
  • dowiedzieć się C++ i napisać rozszerzenie PHP
  • Przekompiluj PHP (lub HipHop?) użyć 2 bajty na int
  • użytkowania Igbinary (użyteczne, ale będzie miał ten sam problem co pakiet())
+0

zdecydowanie używaj funkcji shmop_ * ... poza tym, że mogę tylko myśleć o tym samym, co BarsMonster. –

+1

Czy na pewno nie można używać tabel mysql i pamięci? Być może mógłbyś nawet napisać porównania w formularzu zapytania, aby uniknąć wysyłania danych tam iz powrotem z php –

+0

serializować i unserializować są szybsze niż var_export, btw – raveren

Odpowiedz

4

Nie polecam ostatniego podejścia. :-)

Do szybkiego rozwiązania, chciałbym Pack 2 dla swoich liczb całkowitych w 1 PHP całkowitej za pomocą tego:

$big = $int1 + ($int2<<16); 

And uppack as: 

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

Ponadto, duże kciuki za korzystanie z pamięci współdzielonej. To sprawi, że Twoja aplikacja będzie szybsza.

+0

Wygląda to ładne rozwiązanie. Liczby całkowite muszą być dostępne losowo, więc może być trochę narzutów procesora z tym, ale jeśli to działa, to oszczędności pamięci powinny być tego warte. Zrobię to ... – dave1010

2

To nie jest PHP zadanie zostało zaprojektowane.

polecam Ci napisać aplikację, która ma dane w pamięci i wykonuje obliczenia z nim, a następnie interfejs z nim w PHP, aby uzyskać wyniki.

PHP wielkość całkowita jest faktycznie 64-bitowych na większości 64-bitowych platformach uniksowych.

Pamięć współdzielona nie jest zbyt dobrym rozwiązaniem, ponieważ nadal trzeba skopiować dane do pamięci w PHP.

Zapisywanie rozszerzenia przechowującego wszystko w pamięci i dostęp do niego bezpośrednio jest możliwe, ale niezbyt praktyczne, ponieważ w każdym razie musisz użyć pamięci współużytkowanej (lub innego mechanizmu IPC), ponieważ zazwyczaj uruchamiasz kilka procesów PHP.

+0

Chciałbym napisać coś, co łączy się z PHP, ale nie wiedziałbym od czego zacząć. Jakieś wskazówki? – dave1010

+1

Można użyć gniazd lub innej formy przekazywania wiadomości (http://en.wikipedia.org/wiki/Message_passing). W przypadku Javy możesz użyć [most PHP/Java] (http://php-java-bridge.sourceforge.net/). – Artefacto

+0

Dzięki. Tylko część tablicy musiałaby znajdować się w przestrzeni pamięci PHP jednocześnie, więc myślę, że funkcje shmop * mogą * działać. Dzielenie się pamięcią byłoby idealnym rozwiązaniem, ponieważ skalowałoby się znacznie lepiej. – dave1010

1

chciałbym wygenerować i zapisać tablicę w formacie binarnym zapakowane i wyodrębnić numery tylko kiedy trzeba im

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

można uczynić go bardziej wyszukane pisząc klasę implementującą ArrayAccess, tak, że można po prostu użyj myPackedArray [x] zamiast elem (x) w pozostałej części kodu.

Powiązane problemy