2010-03-30 15 views
12

Tengo un script PHP que crea un binary search tree sobre a rather large CSV file (5MB +). Esto es bueno y todo, pero toma aproximadamente 3 segundos leer/analizar/indexar el archivo.PHP - * fast * serialize/unserialize?

Ahora pensé que podría usar serialize() y unserialize() para acelerar el proceso. Cuando el archivo CSV no ha cambiado mientras tanto, no tiene sentido volver a analizarlo.

Para mi horror, encuentro que llamar a serialize() en mi objeto de índice lleva 5 segundos y produce un gran archivo de texto (19 MB), mientras que unserialize() demora insoportablemente 27 segundos para volver a leerlo. Mejoras parecen un poco diferentes. ;-)

Entonces, ¿hay un mecanismo más rápido para almacenar/restaurar gráficos de objetos grandes desde/hacia el disco en PHP?

(Para aclarar: Estoy buscando algo que toma significativamente menor al citado 3 segundos para hacer el trabajo de-serialización.)

+0

Por qué no almacenar la información que se encuentra en el archivo en una base de datos? – RJD22

+0

Porque el script es parte de una herramienta que específicamente no desea usar una dependencia de base de datos. – Tomalak

+0

¿Cómo son sus objetos de índice? – user187291

Respuesta

3

Parece que la respuesta a su pregunta es no.

Incluso si descubres una opción de "formato de serialización binaria", lo más probable es que sea más lento de lo que imaginas.

Por lo tanto, lo que debe tener en cuenta al usar (como han mencionado otros) es una base de datos, memcached o en un servicio web en línea.

me gustaría añadir las siguientes ideas, así:

  • almacenamiento en caché de peticiones/respuestas
  • su script PHP no hace apagado, pero se convierte en un servidor de red para responder a consultas
  • o, se atreven yo digo que, cambie la estructura de datos y el método de consulta que está utilizando actualmente
+0

Creo que estás aquí mismo. Lástima, pero así es como es. – Tomalak

+0

Tiene una gran fuente de datos que ofrece muchas ideas creativas, estoy seguro de que encontrará algo muy sencillo. – zaf

1

Si quieres velocidad, escribir o leer desde el archivo sistema en menos que óptimo.

En la mayoría de los casos, un servidor de base de datos podrá almacenar y recuperar datos mucho más eficientemente que un script PHP que está leyendo/escribiendo archivos.

Otra posibilidad sería algo así como Memcached.

La serialización de objetos no se conoce por su rendimiento sino por su facilidad de uso y definitivamente no es adecuada para manejar grandes cantidades de datos.

+0

¿No hay un formato de serialización binario para PHP que escribe bytes de memoria en el disco y simplemente los vuelve a leer? Si el CSV es todas las cadenas y el objeto de índice en realidad contiene menos información que el archivo de texto, ¿por qué debe ser su forma serializada tan inflada? – Tomalak

+0

@Tomalak: echa un vistazo a pack/unpack – Robert

+0

@Robert: Parece que el paquete funciona solo para valores individuales, no para objetos complejos. – Tomalak

2

veo dos opciones aquí

serialización de cadena, en la forma más simple algo así como

write => implode("\x01", (array) $node); 
    read => explode() + $node->payload = $a[0]; $node->value = $a[1] etc 

serialización binaria con el paquete()

write => pack("fnna*", $node->value, $node->le, $node->ri, $node->payload); 
    read => $node = (object) unpack("fvalue/nre/nli/a*payload", $data); 

Sería interesante referente ambas opciones y compara los resultados.

+0

El árbol tiene un nodo raíz. ¿Sería suficiente 'pack()' ese nodo raíz, es decir, ¿empacaría todo el gráfico? – Tomalak

+0

no, el paquete solo procesa las variables individuales – user187291

+2

Entonces no es una opción, me temo. : - \ – Tomalak

6

var_export debe ser muy rápido ya que PHP no tendrá que procesar la cadena en absoluto:

// export the process CSV to export.php 
$php_array = read_parse_and_index_csv($csv); // takes 3 seconds 
$export = var_export($php_array, true); 
file_put_contents('export.php', '<?php $php_array = ' . $export . '; ?>'); 

Luego incluyen export.php cuando lo necesite:

include 'export.php'; 

Dependiendo de su servidor web configurado, puede que tenga que chmod export.php para que sea ejecutable en primer lugar.

+5

Sé que esto es viejo, pero hay una manera mejor, todavía usando el mismo código. en lugar de tener 'file_put_contents ('export.php', '');', simplemente use 'file_put_contents ('export.php', ''); '. Y en lugar de 'incluir 'export.php';', use '$ data = include 'export.php';'. –

+0

Esta es una solución increíble. Siempre uso var_export 'ed data en includes, ¡y esto lo hace un poco más fácil! – Gfra54

-1

SQLite viene con PHP, puede usarlo como su base de datos. De lo contrario, podrías intentar usar sesiones, entonces no tienes que serializar nada, solo guardas el objeto PHP sin procesar.

+0

¿Puedo compartir el objeto entre sesiones en PHP? – Tomalak

+0

No se pudo compartir entre diferentes sesiones. Aunque probablemente puedas hacer que todos usen la misma sesión configurando una ID de sesión personalizada. De lo contrario, tendría que considerar el uso de la memoria compartida. http://php.net/manual/en/book.shmop.php –

+0

Solo una nota rápida en caso de que alguien se tropiece con ella - ** NO ** usa sesiones para almacenar objetos grandes, y aún más - hazlo ** NO ** permita que las personas compartan la misma sesión. En primer lugar, esto frustra el objetivo de utilizar una sesión y, dado que solo un usuario puede acceder a una ID de sesión a la vez, limitará de manera efectiva el procesamiento de solicitudes a ** un ** solo. ¡La sesión tiene que cargarse desde el disco/base de datos de todos modos! – SteveB

0

¿Qué hay de usar algo como JSON para un formato para almacenar/cargar los datos? No tengo idea de qué tan rápido es el analizador JSON en PHP, pero generalmente es una operación rápida en la mayoría de los idiomas y es un formato liviano.

http://php.net/manual/en/book.json.php

+0

Sí, eso funcionaría para datos, no para gráficos de objetos. Estaba buscando algo que volcara todo el gráfico de objetos en el disco para no tener ninguna penalización por volver a crearlo (en términos de análisis, comprobación de errores, construcción de objetos). – Tomalak

+0

JSON funcionará bien, a menos que el gráfico de objetos sea cíclico. –

+0

JSON no puede representar referencias. Puede representar jerarquías. Ni siquiera es necesario tener referencias cíclicas, tan pronto como hay una referencia de 'padre', se termina. Además, la serialización/no serialización no es lo que tenía en mente. – Tomalak

4

En primer lugar hay que cambiar la forma en que funciona el programa. divide el archivo CSV en trozos más pequeños. Este es un datastore de IP, supongo. .

Convierta todas las direcciones IP a entero o largo.

Por lo tanto, si llega una consulta, puede saber qué parte buscar. Hay <?php ip2long() /* and */ long2ip(); funciones para hacer esto. De modo que 0 a 2^32 convierten todas las direcciones IP en 5000K/50K totalizan 100 archivos más pequeños. Este enfoque le proporciona una serialización más rápida.

Piense inteligente, código ordenada;)