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

Ruby Discussion :

Ruby foire sur une expression régulière, mais pourquoi ?


Sujet :

Ruby

  1. #1
    Membre averti

    Homme Profil pro
    Analyste d'exploitation
    Inscrit en
    Décembre 2003
    Messages
    333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Analyste d'exploitation
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2003
    Messages : 333
    Points : 382
    Points
    382
    Billets dans le blog
    1
    Par défaut Ruby foire sur une expression régulière, mais pourquoi ?
    Bonjour,

    j'ai un problème avec ruby (version ruby-2.2.4-x64-mingw32, je suis sous Windows 10). Mon action est simple : je cherche une chaîne 123456$ dans un fichier de 2 Go.

    Voici le code, rien de bien spécial

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    counter = 0
    counter2 =0
    #$/ = "\r\n"
    filename = "..\\..\\Tests\\10-million-combos.txt"
    content = File.readlines filename
    content.each{
      |line| counter+=1;
      if line.match(/123456$/)
        counter2 += 1
      end			
    }
    p counter
    p counter2
    Ca marche sur de petit volume, mais dès que je passe sur ce gros fichier, ça ne me donne plus les bons chiffres. Au départ il y avait un problème semble t il de CR et CR+LF ou Lf mixé que j'ai conformé depuis, tout est sensé être CR+LF. Mais il me compte 86931744 lignes au lieu de 185866730 lignes et 6983 occurrences au lieu de 14901 (vérifié avec grep 123456$ et wc -l.

    D’où peut venir le problème à votre avis ???

  2. #2
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    Il faut échapper le caractère $ : \$
    L'expression exacte serait : /123456\$/

    Voici un exemple sur le site http://rubular.com/
    http://rubular.com/r/VNBtk8kBs5

    @+

  3. #3
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 858
    Points : 6 556
    Points
    6 556
    Par défaut
    Citation Envoyé par john.fender Voir le message
    un fichier de 2 Go
    ...
    rien de bien spécial
    ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    content = File.readlines filename
    Ça c'est quand même bien spécial. Car tu charges l'intégralité d'un fichier de 2Go dans un array (qui donc occupera plus de 2Go en mémoire).
    Quand tu attaques un fichier potentiellement conséquent, il faut éviter comme la peste de le slurper (=tout charger d'un coup). Tu dois au contraire privilégier la lecture ligne par ligne:

    Code ruby : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    fh = File.open("filename", "r")
    fh.each_line do |line|
        nb_line = nb_line.next
        if (/123456$/ =~ line) != nil
            nb_match = nb_match.next
        end
    end

    En passant, pas besoin d'utiliser wc avec grep qui dispose de l'option -c qui renvoie directement le nombre de lignes où la correspondance a été trouvée.
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  4. #4
    Membre averti

    Homme Profil pro
    Analyste d'exploitation
    Inscrit en
    Décembre 2003
    Messages
    333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Analyste d'exploitation
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2003
    Messages : 333
    Points : 382
    Points
    382
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    je viens de trouver vos réponses !

    Bon, en fait la solution c'est de préciser le mode binary (je suppose que c'est sinon c'est plaintext ?)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    open("..\\Tests\\10-million-combos_LF.txt","rb") do |content|
    c'est quand même bien spécial. Car tu charges l'intégralité d'un fichier de 2Go dans un array (qui donc occupera plus de 2Go en mémoire
    Non, ligne par ligne justement dans ce cas là. Pour moi, travailler sur un fichier de 2 Go en 2016 ce n'est pas spécial, surtout avec un langage récent, cela ne devrait pas être un problème.

    L'expression exacte serait : /123456\$/
    Ca marche sans. Voir même ça marche pas du tout avec (il me cherche l'occurence 123456 avec le symbole $ à la fin).

  5. #5
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 858
    Points : 6 556
    Points
    6 556
    Par défaut
    Citation Envoyé par john.fender Voir le message
    Non, ligne par ligne justement dans ce cas là. Pour moi, travailler sur un fichier de 2 Go en 2016 ce n'est pas spécial, surtout avec un langage récent, cela ne devrait pas être un problème.
    Attention, tu appliques ta regex sur chaque lignes séparément certes, mais le problème c'est qu'au préalable tu as stocké toutes ces lignes dans un tableau au lieu de les lire au fur et à mesure depuis ton fichier.

    2Go ce n'est pas rien même en 2016! Et quand bien même tu tournerais sur une machine équipée de 32Go de mémoire, la différence de performance sera nette entre une approche qui utilise each_line et l'autre qui en plus de devoir lire le fichier en une seule fois (ce qui monopolise le hd pendant prés d'une seconde) va encombrer plus de 2Go de mémoire avec un tableau monstrueux qu'il faut construire et qui ne sert pas à grand chose.

    J'ai fait quelques tests sur un gros fichier > 1Go pour illustrer mon propos, c'est ~40% plus rapide de charger les lignes au fur et à mesure et c'est beaucoup plus léger pour la mémoire et le disque.

    Pour ce qui est du "langage récent", c'est une idée fantaisiste! Ruby date de 1995, avec python (1991) on atteint 50%, avec Perl (1987) c'est carrément 75% (et en 38 caractères sans le nom du fichier).
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  6. #6
    Membre averti

    Homme Profil pro
    Analyste d'exploitation
    Inscrit en
    Décembre 2003
    Messages
    333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Analyste d'exploitation
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2003
    Messages : 333
    Points : 382
    Points
    382
    Billets dans le blog
    1
    Par défaut
    Hello,

    au préalable tu as stocké toutes ces lignes dans un tableau au lieu de les lire au fur et à mesure depuis ton fichier
    Heu, non, je ne monte justement pas 2 Go en mémoire avec ce code et je t'enjoins à le vérifier par toi mêle. C'est un de mes pré-requis de ne pas monter 2 go en mémoire, en particulier parce que je vise des logs plus lourds justement !!!

    Pour ce qui est du "langage récent", c'est une idée fantaisiste! Ruby date de 1995
    Ce n'est pas seulement la date. Un langage mature avec le temps et l'usage et en fonction de sa conception intiale. C et C++ sont bien plus vieux et ont un parc d'utilisateurs sans commune mesure et 40 compilos différents. Java date de la même époque mais a une audience et un développement tout autre. Ne parlons pas de C# avec un éditeur aux moyens très largement supérieur...

    Perl, c'est difficile de comparer là aussi, c'est son domaine prédilection, là ou il pêche c'est l'objet, il a pas été fait pour ça, comme php d'ailleurs, et c'est là ou justement Ruby va briller. Perl pour moi c'est normal que ça marche bien sur ce type de test, il a été fait pour !

    Ce qui est surprenant, c'est d'en être aussi éloigné (plus du double quand même !) : J'ai 28s en C#, 30s en Perl (!), 80s en Ruby, 150 en Python... Ca me déçoit vraiment pour Python d'ailleurs au passage.

    Cheers.

  7. #7
    Membre extrêmement actif
    Avatar de Madmac
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2004
    Messages
    1 685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Alimentation

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 685
    Points : 1 376
    Points
    1 376
    Billets dans le blog
    7
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    a = IO.readlines("testfile")
    a[0]   #=> "This is line one\n"

    Selon la documentation, c'est bien un tableau de 2G qui est créé.

  8. #8
    Membre averti

    Homme Profil pro
    Analyste d'exploitation
    Inscrit en
    Décembre 2003
    Messages
    333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Analyste d'exploitation
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2003
    Messages : 333
    Points : 382
    Points
    382
    Billets dans le blog
    1
    Par défaut
    Et bien faites le test.

  9. #9
    Membre extrêmement actif
    Avatar de Madmac
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2004
    Messages
    1 685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Alimentation

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 685
    Points : 1 376
    Points
    1 376
    Billets dans le blog
    7
    Par défaut
    Citation Envoyé par john.fender Voir le message
    Et bien faites le test.
    Ho surprise, ton code bouffe 2 G !

    j'ai fais le test avec la page html de ce site: https://www.sitepoint.com/uno-use-si...ment-rest-api/


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    counter = 0
    counter2 =0
    content = []
    p 'la longueur du tableau au debut:' + content.size.to_s
    #$/ = "\r\n"
    filename = "./Uno! Use Sinatra to Implement a REST API.html"
    content = File.readlines filename
    content.each{
      |line| counter+=1;
      if line.match(/123456$/)
        counter2 += 1
      end			
    }
     
    p counter
    p counter2
    p 'la longueur du tableau à la fin:' + content.size.to_s
    p content
     
    #https://www.sitepoint.com/uno-use-sinatra-implement-rest-api/
    Cette petite page a produit un tableau de 1366 cellules ....

    Je ne sais pas par quel moyen tu es arrivé à la conclusion que ce n'était pas le cas. la méthode "size" retourne le nombre d'objet, pas son poids en kilobytes ,,,

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Demande d'aide sur une expression régulière
    Par bubulemaster dans le forum Débuter
    Réponses: 4
    Dernier message: 03/04/2008, 13h19
  2. Problème sur une expression régulière
    Par GregLig dans le forum Langages de programmation
    Réponses: 2
    Dernier message: 22/12/2007, 13h34
  3. Un peu d'aide sur une expression régulière particulier
    Par ruana dans le forum Général Python
    Réponses: 2
    Dernier message: 03/06/2007, 19h04
  4. [RegEx] Aide sur une expression régulière toute simple
    Par tchoumak dans le forum Langage
    Réponses: 3
    Dernier message: 29/11/2005, 15h46
  5. Problème sur une expression régulière
    Par Verbal-Quint dans le forum Langage
    Réponses: 6
    Dernier message: 12/11/2004, 10h54

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