2010-10-21 13 views
9

Je travaille sur un fichier incrémental d'environ 1Go et je veux rechercher un motif particulier. Actuellement j'utilise des expressions régulières Java, avez-vous une idée de comment je peux le faire plus rapidement?Comment la recherche de motif peut-elle être plus rapide?

+2

Les sons de ce type devraient être liés aux E/S. À quelle vitesse un programme qui lit (et supprime) simplement le contenu du fichier s'exécute-t-il? Les expressions régulières devraient être capables d'approcher la même vitesse, ou bien quelque chose ne va pas (comme la mise en mémoire tampon). Si la simple lecture du fichier est trop lente pour vos besoins, alors vous devez envisager une approche différente (voir la discussion de Lucene ci-dessous). –

+0

Pouvez-vous montrer le motif et un peu du fichier. Peut-être que l'expression est lente parce qu'elle n'est pas optimale. Est-ce que votre programme charge le contenu entier du fichier dans une chaîne pour ensuite exécuter l'expression régulière? Est-ce la partie lente? –

Répondre

7

Fondamentalement, vous avez besoin d'une machine d'état capable de traiter un flux. Ce flux étant lié au fichier ... Chaque fois que le fichier grandit, vous lisez ce qui y a été ajouté (comme la commande tail linux qui ajoute à la sortie standard les lignes ajoutées au fichier).

Si vous avez besoin d'arrêter/redémarrer votre analyseur, vous pouvez simplement stocker quelque part la position de départ (qui peut dépendre de la fenêtre dont vous avez besoin pour votre correspondance de modèle) et redémarrer à partir de là. Ou vous pouvez redémarrer à partir de zéro.

Ceci est pour la partie "augmentant le fichier" du problème. Pour la meilleure façon de traiter le contenu, cela dépend de ce dont vous avez réellement besoin, du type de données et du modèle que vous souhaitez appliquer. L'expression régulière est peut-être la meilleure solution: flexible, rapide et relativement pratique. D'après ce que je comprends, Lucene serait bon si vous vouliez faire la recherche de documents correspondant à un contenu en langage naturel. Ce serait un mauvais choix pour faire correspondre toutes les dates ou toutes les lignes avec une propriété spécifique. Aussi parce que Lucene fait d'abord un index du document ... Cela ne serait utile que pour un traitement vraiment lourd car l'indexation en premier lieu prend du temps.

8

Cela ressemble à un travail pour Apache Lucene.

Vous devrez probablement repenser votre stratégie de recherche, mais cette bibliothèque est faite pour faire ce genre de choses et ajouter des index de façon incrémentielle.

Il fonctionne en construisant des index inverses de vos données (documents en langage Lucene), puis en vérifiant rapidement dans les index inverses pour quels documents ont des parties de votre modèle.

Vous pouvez stocker des métadonnées avec les index de document afin de ne pas avoir à consulter le gros fichier dans la majorité des cas d'utilisation.

+0

Le fichier que j'analyse augmente avec le temps. Est-ce possible de faire l'indexation. Je viens de trouver que l'expression régulière est plus lente. Je dois utiliser quelque chose comme Thomson NFA. – Kamahire

+0

Merci Peter pour une réponse rapide. Comment peut-on utiliser Lucern pour le même? Pouvez-vous me donner un échantillon? – Kamahire

+0

Lucene est bon pour le traitement des données textuelles avec un langage naturel à l'intérieur. Selon le format de votre fichier et de votre modèle, cela pourrait ne pas être la meilleure solution. –

4

Vous pouvez essayer d'utiliser les classes Pattern et Matcher pour rechercher des expressions compilées.

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

ou utilisez votre moteur de recherche favori pour la recherche sur les termes:

optimisation java expression régulière ou

performances java expression régulière

+0

J'ai optimisé les expressions régulières. J'ai enlevé le retour arrière. – Kamahire

+1

Est-ce que ça l'a rendu plus rapide? –

4

Je pense que cela dépend de:

  • la structure de vos données (ligne orientée?)
  • la complexité du match
  • la vitesse à laquelle le fichier de données est de plus en plus

Si vos données sont orientées ligne (ou bloc orienté) et une correspondance doit avoir lieu au sein d'une telle unité, vous pouvez faire correspondre jusqu'au dernier bloc complet, et stocker la position du fichier de ce point de terminaison. L'analyse suivante doit commencer à ce point de terminaison (en utilisant éventuellement RandomAccessFile.seek()).

Cela aide particulièrement si les données ne progressent pas aussi rapidement. Si votre correspondance est très complexe mais a un texte fixe distinctif, et que le motif ne se produit pas si souvent, vous pouvez être plus rapide avec un String.contains() et seulement si cela est vrai appliquer le pattern. Comme les motifs ont tendance à être hautement optimisés, il n'est certainement pas garanti d'être plus rapide.

Vous pouvez même envisager de remplacer l'expression régulière en écrivant à la main un analyseur, éventuellement basé sur StringTokenizer ou autre. C'est certainement beaucoup de travail pour bien faire les choses, mais cela vous permettrait de transmettre des informations supplémentaires sur les données dans l'analyseur, ce qui lui permettra d'échouer rapidement. Ce serait seulement une bonne option si vous en savez vraiment beaucoup sur les données que vous ne pouvez pas encoder dans un modèle.

Questions connexes