2010-10-21 12 views
9

Estoy trabajando en aproximadamente 1GB de archivo incremental y quiero buscar un patrón en particular. Actualmente estoy usando expresiones regulares de Java, ¿tienes alguna idea de cómo puedo hacer esto más rápido?¿Cómo puede la búsqueda de patrones hacer más rápido?

+2

Suena como que esto debe ser vinculado a E/S. ¿Qué tan rápido funciona un programa que simplemente lee (y descarta) el contenido del archivo? Las expresiones regulares deberían poder acercarse a la misma velocidad, o si algo está yendo mal (como el almacenamiento en búfer). Si simplemente leer el archivo es demasiado lento para sus propósitos, entonces debe considerar un enfoque diferente (c.f. la discusión de Lucene a continuación). –

+0

Puedes mostrar el patrón y un poco del archivo. Tal vez la expresión es lenta porque no es óptima. ¿Su programa carga todo el contenido del archivo en una cadena para luego ejecutar la expresión regular? ¿Esa es la parte lenta? –

Respuesta

7

Básicamente lo que necesita es una máquina de estado que pueda procesar una secuencia. Esta secuencia está limitada al archivo ... Cada vez que crece el archivo, lee lo que se le ha agregado (como el comando tail linux que se agrega a la salida estándar de las líneas agregadas al archivo).

Si necesita detener/reiniciar su analizador, puede simplemente almacenar en algún lugar la posición de inicio (que puede depender de la ventana que necesite para la coincidencia de patrones) y reiniciar desde allí. O puede reiniciar desde cero.

Esto es para la parte de "aumento de archivos" del problema.

Para la mejor manera de procesar el contenido, depende de lo que realmente necesita, qué tipo de datos y patrón desea aplicar. La expresión regular es quizás la mejor solución: flexible, rápida y relativamente conveniente.

Desde mi entender, Lucene sería bueno si quisiera hacer una búsqueda de documentos que coincida con algún contenido de lenguaje natural. Esta sería una mala elección para hacer coincidir todas las fechas o todas las líneas con una propiedad específica. También porque Lucene primero hace un índice del documento ... Esto ayudaría solo para un procesamiento realmente pesado ya que la indexación en primer lugar toma tiempo.

8

Suena como un trabajo para Apache Lucene.

Probablemente tendrá que reconsiderar su estrategia de búsqueda, pero esta biblioteca está hecha para hacer cosas como esta y agregar índices de forma incremental.

Funciona mediante la creación de índices inversos de sus datos (documentos en el lenguaje de Lucene), y luego revisando rápidamente los índices inversos para los cuales los documentos tienen partes de su patrón.

Puede almacenar metadatos con los índices de documentos para que no tenga que consultar el archivo grande en la mayoría de los casos de uso.

+0

El archivo que estoy analizando está creciendo por tiempo. Es posible hacer indexación. Acabo de descubrir que la expresión regular es más lenta. Tengo que usar algo como Thomson NFA. – Kamahire

+0

Gracias Peter por una pronta respuesta. ¿Cómo puede usar Lucern para lo mismo? ¿Me puedes dar alguna muestra? – Kamahire

+0

Lucene es bueno para procesar datos textuales con lenguaje natural adentro. Dependiendo del formato de su archivo y de su patrón, esta podría no ser la mejor solución. –

4

Puede intentar usar las clases Patrón y Matcher para buscar con expresiones compiladas.

Ver http://download.oracle.com/javase/1.4.2/docs/api/java/util/regex/Pattern.html y http://download.oracle.com/javase/tutorial/essential/regex/

o usar su motor de búsqueda favorito para buscar en los términos:

optimización java expresión regular o

rendimiento de Java expresión regular

+0

He optimizado las expresiones regulares. He eliminado el retroceso. – Kamahire

+1

¿Eso lo hizo más rápido? –

4

Creo que depende de:

  • la estructura de los datos (orientado línea?)
  • la complejidad del partido
  • la velocidad a la que el archivo de datos está creciendo

Si los datos se orienta línea (o orientado al bloque) y debe producirse una coincidencia dentro de dicha unidad que puede coincidir hasta el último bloque completo, y almacenar la posición del archivo de ese punto final. La próxima exploración debería comenzar en ese punto final (posiblemente usando RandomAccessFile.seek()).

Esto ayuda especialmente si los datos no crecen tan rápido.

Si su partido es muy compleja, pero tiene un texto fijo distintivo, y el patrón no ocurre muy a menudo que puede ser más rápido por un String.contains() y sólo si eso es cierto aplicar el patrón. Como los patrones tienden a estar altamente optimizados, definitivamente no se garantiza que sean más rápidos.

Incluso puede pensar en reemplazar la expresión regular mediante la escritura manual de un analizador, posiblemente basado en StringTokenizer o algo así. Definitivamente, eso es mucho trabajo para hacerlo bien, pero le permitiría pasar algo de inteligencia adicional sobre los datos al analizador sintáctico, permitiéndole fallar rápidamente. Esto solo sería una buena opción si realmente sabes mucho sobre los datos que no puedes codificar en un patrón.

Cuestiones relacionadas