2010-09-07 9 views
5

Antecedentes: tengo una gran matriz 2D de enteros que necesito cargar en la memoria en PHP para cada solicitud de Apache. Quiero que ocupe menos memoria.¿Es posible usar ints cortos (16 bits) en PHP?

PHP almacena ints en PHP_INT_SIZE bytes, que son 32 bits en la mayoría de los sistemas. Todos los enteros son menores que 2^16, lo que significa que podrían ser short int (por ejemplo, en C). ¿Estoy en lo cierto al pensar que almacenar las entradas como cortas ocuparía la mitad de la RAM?

Idealmente me gustaría ser capaz de hacer:

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

Más información:

  • El conjunto ocupa alrededor de 100 MB de RAM y se genera mediante la inclusión de un 30MB var_export() volcar
  • La matriz está escrita en un proceso cron. Solo la lectura debe ser eficiente en cuanto a la memoria (y rápida)
  • Las únicas operaciones que necesito hacer en los enteros son compararlas todas (<,>, ===) y luego leer algunas de ellas (similar al Floyd-Warshall algorithm)
  • lectura cada valor de una DB es demasiado lento, ya que hay unos pocos cientos de millones de lecturas por petición

Algunas ideas locas:

  • uso pack()/unpack() pero eso todavía tienda los valores como 32 bi t enteros cuando se instalan los
  • tienda los valores que los píxeles de una imagen y de uso de PHP de GD library para leerlos (¿Esto sería lento)
  • Uso shmop_read() y tienen los procesos de Apache comparten la matriz
  • Memcached podría funcionar, pero no tengo ninguna experiencia con ella y yo supongo que sería muchas veces más lento que una matriz PHP nativo
  • aprender C++ y escribir una extensión de PHP
  • recompilación PHP (o HipHop?) utilizar 2 bytes para enteros
  • use Igbinary (útil, pero tendrá el mismo problema que el paquete())
+0

definitivamente uso las funciones shmop_ * ... aparte de eso, solo puedo pensar en lo mismo que se le ocurre a BarsMonster. –

+1

¿Estás seguro de que no puedes usar mysql y tablas de memoria? Tal vez incluso podría escribir las comparaciones en forma de consulta para evitar enviar y recibir datos con php –

+0

serialize y unserialize son más rápidos que var_export, btw – raveren

Respuesta

4

No recomendaría el último enfoque. :-)

Para la solución rápida, me Pack 2 en los números enteros 1 número entero PHP usando la siguiente:

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

And uppack as: 

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

Además, los pulgares ascendentes grandes para el uso de memoria compartida. Esto hará que tu APLICACIÓN sea más rápida.

+0

Parece una buena solución. Es necesario acceder aleatoriamente a los enteros, de modo que podría haber una sobrecarga de CPU con esto, pero si funciona, los ahorros de memoria deberían valer la pena. Voy a intentarlo ... – dave1010

2

Esta no es una tarea para la que PHP haya sido diseñado.

Te recomiendo que escribas una aplicación que tenga los datos en la memoria y haga los cálculos con ella y luego interactúes con ella en PHP para obtener los resultados.

El tamaño entero de PHP es en realidad de 64 bits en la mayoría de las plataformas tipo Unix de 64 bits.

La memoria compartida no es una muy buena opción porque todavía tiene que copiar los datos al espacio de memoria de PHP.

Escribir una extensión que guarde todo en la memoria y acceda directamente es posible pero no muy práctico ya que debe usar memoria compartida (o algún otro mecanismo IPC) de todos modos, porque normalmente ejecuta varios procesos PHP.

+0

Me gustaría escribir algo que interactúe con PHP, pero no sabría por dónde empezar. ¿Alguna sugerencia? – dave1010

+1

Puede usar sockets o alguna forma de [mensaje que pase] (http://en.wikipedia.org/wiki/Message_passing). Para Java, puede usar el [puente PHP/Java] (http://php-java-bridge.sourceforge.net/). – Artefacto

+0

Gracias. Solo una parte de la matriz debería estar en el espacio de memoria de PHP a la vez, por lo que creo que las funciones de * shmop * pueden * funcionar. Compartir la memoria sería la solución ideal, ya que escalaría mucho mejor. – dave1010

1

que me gustaría generar y almacenar la matriz en un formato binario para llevar y extraer los números sólo cuando los necesite

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

puede hacer que sea más elegante escribiendo una clase que implementa ArrayAccess, para que pueda simplemente utilice myPackedArray [x] en lugar de elem (x) en el resto del código.

Cuestiones relacionadas