IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Perl Discussion :

écrire un file grep optimisé


Sujet :

Langage Perl

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Mai 2007
    Messages
    17
    Détails du profil
    Informations personnelles :
    Âge : 56

    Informations forums :
    Inscription : Mai 2007
    Messages : 17
    Par défaut [Résolu] écrire un file grep optimisé
    Bonjour,

    je suis nouveau sur ce forum, j'ai 10 ans d'expérience. Je me remets au Perl après 8 ans, donc je me dois de rafraîchir un peu ma mémoire.

    J'ai une problématique simple: rechercher de multiples (en centaines de milliers) occurences de chaînes dans une collection de fichiers. Réflexe de base: utiliser find et grep. Sauf que là, c'est fgrep pour accélérer, avec son option -f (prends toutes les occurrences de chaînes référencées dans mon fichier après le -f et matche).

    Petit hic: ce fgrep (fast grep !) prend 15mns sur un seul fichier un peu gros (220K). Or c'est mon repository CVS que je dois analyser => dans deux mois ce ne sera pas terminé. Donc je récris une sorte de fgrep optimisé.

    La solution que j'ai trouvée, qui est intermédiaire mais que je souhaite améliorer, c'est de hasher les entrées de mon fichier passé en -f (fichier de mes occurrences, appelons-le "keysfile"), puis de lire le fichier à grepper (appelons-le datafile), de concaténer tout le fichier datafile en une seule GROSSE chaîne, et d'itérer sur les hash keys (unicité garantie donc) en matchant chaque clef sur la GROSSE chaîne (le datafile donc).

    C'est rapide (20 fois plus que grep) mais pas assez encore. Ce que je recherche en fait, c'est une sorte de primitive qui matcherait toutes les entrées d'un hash ou d'un tableau sur une chaîne à analyser. Est-ce que cela existe ?

    J'ai une dernière cartouche pas encore tirée: constituer une chaîne de caractères des clefs sous forme de regexp: exp1|exp2|exp3 etc... et passer cette chaîne à grep.

    Qu'en pensez-vous ?

    Merci d'avance.
    Christophe.

  2. #2
    Membre émérite
    Avatar de GnuVince
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2004
    Messages
    679
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2004
    Messages : 679
    Par défaut
    Si ce soit-disant "fast grep" prend 15 minutes pour analyser un fichier de 220 KB, ne l'utilise pas. Essaye le bon vieux grep normal. Il est très rapide ici:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    [vince@mithril: /var/www/logs]% time grep "13/Mar/2007" access_log > /dev/null
    grep "13/Mar/2007" access_log > /dev/null  1.04s user 0.73s system 20% cpu 8.491 total
    [vince@mithril: /var/www/logs]% du -h access_log
    33.9M   access_log
    [vince@mithril: /var/www/logs]%
    Et c'est pas une machine à tout casser: Pentium III 450 MHz, 128 MB de mémoire et un disque dur IDE de 10GB @ 5400 RPM.

  3. #3
    Expert confirmé
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Par défaut
    A mon avis, réécris ça en Perl avec File::Find::Rule et des regexps compilées avec Regexp::Assemble et ton problème de performance sera réglé.

    --
    Jedaï

  4. #4
    Membre averti
    Inscrit en
    Mai 2007
    Messages
    17
    Détails du profil
    Informations personnelles :
    Âge : 56

    Informations forums :
    Inscription : Mai 2007
    Messages : 17
    Par défaut
    Citation Envoyé par Jedai
    A mon avis, réécris ça en Perl avec File::Find::Rule et des regexps compilées avec Regexp::Assemble et ton problème de performance sera réglé.

    --
    Jedaï
    Là non plus ça ne me semble pas être la solution. En effet, ce que tu me propose consiste à faire le find depuis perl (le find UNIX est pour info extrêmement rapide, son retour me constitue une liste que je parcours ensuite avec n threads parallèles), puis à optimiser le matching avec la version assembleur des regexp. Ceci serait efficace si la nature de mon pb consistait à améliorer les perfs du parcours des fichiers (je n'ai aucun pb ici) où à optimiser le matching (là encore je n'ai aucun pb).

    Mon pb est bel et bien différent: il consiste à éviter d'itérer sur les patterns à matcher sur chacun des fichiers (une liste de 163321 valeurs est à matcher sur tous les fichiers, et c'est cette itération même qui est lente, pas le find ni le matching).

    D'où ma question initiale: comment ne pas itérer sur les regexp, et dire à une fonction interne d'appliquer toutes mes regexps en une fois sur chacun des fichiers.

    En espérant avoir été plus clair cette fois-ci.

  5. #5
    Membre émérite
    Avatar de GnuVince
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2004
    Messages
    679
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2004
    Messages : 679
    Par défaut
    Si ma mémoire ne me trompe pas, il est plus rapide d'itérer sur plusieurs patterns que d'utiliser un regex très compliqué.

    Peut-être en nous parlant du problème que vous essayez de résoudre nous pourrions trouver une solution différente qui serait plus rapide. J'ai vraiment beaucoup de misère à imaginer un problème qui nécessite 163,000 match de regex!

  6. #6
    Membre averti
    Inscrit en
    Mai 2007
    Messages
    17
    Détails du profil
    Informations personnelles :
    Âge : 56

    Informations forums :
    Inscription : Mai 2007
    Messages : 17
    Par défaut
    Citation Envoyé par GnuVince
    Si ma mémoire ne me trompe pas, il est plus rapide d'itérer sur plusieurs patterns que d'utiliser un regex très compliqué.

    Peut-être en nous parlant du problème que vous essayez de résoudre nous pourrions trouver une solution différente qui serait plus rapide. J'ai vraiment beaucoup de misère à imaginer un problème qui nécessite 163,000 match de regex!
    OK, c'est un premier élément de réponse. Mon pb est exposé au début de mon premier post. J'ai une liste de 163 000 valeurs, toutes ces valeurs doivent être recherchées dans une collection de fichiers. On recherche en vérité si des valeurs ont été codées en dur dans tout notre code. Et ces valeurs sont au nb de 163000, ce n'est pas réductible.

  7. #7
    Membre averti
    Inscrit en
    Mai 2007
    Messages
    17
    Détails du profil
    Informations personnelles :
    Âge : 56

    Informations forums :
    Inscription : Mai 2007
    Messages : 17
    Par défaut Ce n'est pas cela...
    Citation Envoyé par GnuVince
    Si ce soit-disant "fast grep" prend 15 minutes pour analyser un fichier de 220 KB, ne l'utilise pas. Essaye le bon vieux grep normal. Il est très rapide ici:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    [vince@mithril: /var/www/logs]% time grep "13/Mar/2007" access_log > /dev/null
    grep "13/Mar/2007" access_log > /dev/null  1.04s user 0.73s system 20% cpu 8.491 total
    [vince@mithril: /var/www/logs]% du -h access_log
    33.9M   access_log
    [vince@mithril: /var/www/logs]%
    Et c'est pas une machine à tout casser: Pentium III 450 MHz, 128 MB de mémoire et un disque dur IDE de 10GB @ 5400 RPM.
    Vous n'avez pas bien lu. Je parle du fgrep utilisé avec son option -f. Rien à voir. Le fgrep sur un fichier de 33Mo est absolument instantanné (fgrep est un standard UNIX au passage, plus rapide que le "bon vieux grep") utilisé comme dans votre exemple, bien évidemment.

    Ce n'est pas ce que je fais.

    Je grep en -f, c'est à dire que je recherche chacune des occurrences d'un fichier, ça revient à dire grep chaine 1 ou chaine2 ou chaine 3 etc... avec en l'occurrence 163321 occurrences, ce sur une fichier de 220K. Soit en produit cartésien du pattern matching sur 35 Gos...

Discussions similaires

  1. Écrire Input File pour Flex
    Par zitou20 dans le forum Autres éditeurs
    Réponses: 0
    Dernier message: 21/11/2014, 17h30
  2. Writer ne veut pas écrire dans File
    Par Gaspard22 dans le forum Général Java
    Réponses: 1
    Dernier message: 27/06/2013, 11h42
  3. écrire un texte au file du traie dans une bannière
    Par pouktoro dans le forum ActionScript 3
    Réponses: 0
    Dernier message: 08/11/2011, 16h05
  4. Réponses: 2
    Dernier message: 04/12/2009, 19h32
  5. Question simple pour écrire dans une File
    Par HeyItsIan dans le forum Langage
    Réponses: 1
    Dernier message: 03/01/2007, 01h40

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo