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 :

Attribuer un tableau à chaque élément d'un tableau existant


Sujet :

Langage Perl

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 69
    Points : 34
    Points
    34
    Par défaut Attribuer un tableau à chaque élément d'un tableau existant
    Bonjour,

    Dans un script, j'ai un tableau contenant 65536 valeurs, soit quatre caractères hexadécimaux dans tous les ordres possibles (0000,0001,0002,...,ffff).

    Je crée ce tableau, puis dans mon script, je lis un fichier texte dont les lignes commencent par des caractères hexadécimaux, par exemple a23f, b14a, etc.

    Ce que j'aimerais, c'est attribuer les lignes de mon fichier aux éléments correspondants dans mon tableau.

    Par exemple me retrouver avec :

    @array = ( [ 0000, [ligne1, ligne2, ligne3, etc] ], [ 0001, [ligne1,ligne2,ligne3, etc] ], ...).

    En gros, comment déclarer un tableau dans un élément d'un tableau existant ? Je précise que je débute en perl et que je n'ai pas de code sous la main, justement je cherche comment faire ça pour attaquer. J'avais essayé vite fait des trucs du genre push @array[$index], ligne1; Dans une boucle, mais ça ne fonctionne pas, on me dit "Not an ARRAY reference".

    Comment est-ce que je devrais procéder ?

    Merci

  2. #2
    Membre éprouvé Avatar de Gardyen
    Homme Profil pro
    Bio informaticien
    Inscrit en
    Août 2005
    Messages
    637
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bio informaticien

    Informations forums :
    Inscription : Août 2005
    Messages : 637
    Points : 1 050
    Points
    1 050
    Par défaut
    Bonjour,

    il s'agit d'un problème de références, consulte la FAQ sur ce sujet pour plus d'informations

    Ta liste principale @array stocke en fait des références à chaque sous liste.
    Par conséquent, il faut que tu changes tes références (les sous listes) en liste pour le push.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #appel à un élément de ta liste
    my $element = $array[0];
    # déréférencement
    my @sous_liste = @{$element}; # ou @{$array[0]}
    push @sous_liste, $ligne;
    Bon courage !
    Nous les geeks, c'est pas qu'on a une case en moins, c'est juste qu'on compte à partir de zéro.
    Plus les choses changent, plus elles restent les mêmes

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 69
    Points : 34
    Points
    34
    Par défaut
    Merci pour ta réponse.

    J'ai un peu de mal à comprendre ça. D'autant que j'ai oublié un truc dans mon post initial, je me demandais si je pouvais attribuer des index de type string à un tableau, pour par la suite pouvoir appeler mes valeurs par $array[$string].

    En fait le but de l'histoire est d'éviter d'ouvrir et de fermer une multitude de fichiers. J'aimerais créer une sorte de buffer, et lorsqu'il est plein ouvrir un fichier pour écrire plusieurs lignes d'un coup.

    Du coup je commence par créer mon tableau, et j'aimerais attribuer en index les noms de fichiers, si possible. Suite à quoi dans ma boucle je n'aurais qu'a faire quelque chose du genre :

    $array[$nom_de_mon_fichier][ ]*= $ligne;

    Puis lorsque la taille de la seconde dimension du tableau est égale à 100, par exemple, hop j'ouvre mon fichier et j'écris toutes les valeurs contenues dans le tableau en seconde dimension. C'est comme ça que j'aurais fait en php, mais en perl je ne connais pas, je ne sais même pas si c'est faisable.

    Merci pour ton aide

  4. #4
    Membre éprouvé Avatar de Gardyen
    Homme Profil pro
    Bio informaticien
    Inscrit en
    Août 2005
    Messages
    637
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bio informaticien

    Informations forums :
    Inscription : Août 2005
    Messages : 637
    Points : 1 050
    Points
    1 050
    Par défaut
    dans ce cas il te faut utiliser un hash (ou liste associative) plutôt qu'une liste pour stocker tes sous listes.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    my %liste;
    push @{$liste{$nom_fichier}}, $ligne;
    Nous les geeks, c'est pas qu'on a une case en moins, c'est juste qu'on compte à partir de zéro.
    Plus les choses changent, plus elles restent les mêmes

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 69
    Points : 34
    Points
    34
    Par défaut
    Merci pour ta réponse. Je ne connaissais pas les hashs.

    Je lirais ça ce soir en rentrant, si j'ai compris c'est une liste qui associe deux valeurs par paire ? Une clef et une valeur, du coup comme dans un tableau. Et je peux définir une clef sous forme de chaine, liée à une valeur de type tableau donc.

    Je ne comprend pas le code que tu as fourni en revanche, à quoi servent les brackets ?

    Merci et désolé, je ne suis pas habitué à la syntaxe du Perl.

  6. #6
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Un hash (ou table de hachage, ou hachage) est en gros comme un tableau, dont les indices n'ont pas besoin d'être numériques mais sont des chaînes de caractères. C'est en quelque sorte un ensemble de paires clef-valeur (c'est d'ailleurs la définition d'un hachage en Perl 6, mais ce n'est pas le sujet).

    Par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    my %mois = ( jan => 1, fev => 2, mar => 3, avr => 4 ...);
    print 'Numéro du mois de mars: $hash{mar}\n; # imprime 3
    Dans ton cas, l'idée est apparemment d'avoir un hash de tableaux, quelque chose du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    %liste = ( nom_fic1 => [ "ligne0", "ligne1", "ligne2",  ...],
               nom_fic2 =>  [ "ligne0", "ligne1", "ligne2", ...],
             );
    (ligne0 de nom_fic1 et ligne0 de nom_fic2 n'ont rien à voir. Les numéros sur une ligne représentent juste l'indice dans les tableaux respectifs).

    Les noms de fichiers sont les clefs du hash, et les valeurs du hash sont des références (sortes de pointeurs) vers des tableaux, c'est-à-dire que chaque valeur du hash est l'adresse mémoire d'un tableau.

    Pour afficher la ligne1 de fic2, j'écris:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    print $liste{nom_fic2}[1], "\n";

    Ce que l'on pourrait décomposer en:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    my $fic_ref = $liste{nom_fic2};      # maintenant $fic_ref contient quelque chose du style : ARRAY(0x600633838), l'adresse mémoire du tableau
    # voir le tableau pointé par $fic_ref:
    print " @{$fic_ref}";                # affiche "ligne0 ligne1 ligne2".
    print ${$fic_ref}[1];                # imprime ligne1
                           # ce qui peut se simplifier en:
    print $$fic_ref[1];                  # idem
    La première ligne de code récupère une référence vers le tableau.
    Dans la seconde, le ${...} sert à dire: je veux déréférencer le tableau, je veux accéder au tableau pointé par $fic_ref, et [1] précise quel élément du tableau je désire

    En le faisant pour de vrai sous le debugger Perl, j'ai:
    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
    22
    23
    24
     
      %liste = ( nom_fic1 => [ "ligne0", "ligne1", "ligne2",], nom_fic2 =>  [ "ligne0", "ligne1", "ligne2",]);
      ...
      # Affichage de la structure de donnée:
     
     x \%liste
    0  HASH(0x60064f248)
       'nom_fic1' => ARRAY(0x600652e10)
          0  'ligne0'
          1  'ligne1'
          2  'ligne2'
       'nom_fic2' => ARRAY(0x600652e40)
          0  'ligne0'
          1  'ligne1'
          2  'ligne2'
    ...
      $fic_ref = $liste{nom_fic2};
      print $fic_ref ;
    ARRAY(0x600652e40)
     
    ...
      print ${$fic_ref}[0];     # -> ligne 0  
      print ${$fic_ref}[1];     # -> ligne 1
      print $$fic_ref[1];         # -> ligne1
    Maintenant si je jeux ajouter des éléments au tableau pointé par $fic_ref, je vais utiliser @{$fic_ref} pour déréférencer $fic_ref, mais je mets cette fois une @ parce que je ne peux faire un push que sur un tableau:
    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
     
         push  @{$fic_ref}, "ligne3";
     
    # en simplifiant comme précédemment:
     
         push @$fic_ref, "ligne4";
     
    # affichage de $fic_ref: 
     
         x $fic_ref
    0  ARRAY(0x600652e40)
       0  'ligne0'
       1  'ligne1'
       2  'ligne2'
       3  'ligne3'
       4  'ligne4'
    Enfin, pour ajouter des lignes à nom_fic1 en utilisant toute la structure %liste, on obtient:
    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
     
    push @{$liste{nom_fic1}}, "ligne6";
     
    # nb: les simplifications antérieures supprimant des accolades ne sont plus possibles, 
    # push @$liste{$nom_fic1}, "ligne6"; ne fonctionnerait pas, car Perl ne peut plus déterminer à quelle partie de l'expression 
    # se rapporte @ alors que ce n'était pas ambigu auparavant (mais oublie les simplifications pour l'instant)
     
    # Affichage de toute la liste:
    x \%liste
    0  HASH(0x60064f248)
       'nom_fic1' => ARRAY(0x600652e10)
          0  'ligne0'
          1  'ligne1'
          2  'ligne2'
          3  'ligne6'
       'nom_fic2' => ARRAY(0x600652e40)
          0  'ligne0'
          1  'ligne1'
          2  'ligne2'
          3  'ligne3'
          4  'ligne4'
    On voit que l'on a bien ajouté les éléments ligne3 et ligne4 au tableau référencé par nom_fic2 (via $fic_ref) et ligne6 au tableau référencé par nom_fic1.

    Bon, j'ai écrit cela très (trop) vite, j'espère que je n'ai pas fait d'erreur, que c'est clair et que tu comprends maintenant à peu près comment ça marche.

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 69
    Points : 34
    Points
    34
    Par défaut
    Merci encore pour ton aide.

    J'ai réussi à faire marcher mon script, que voici :

    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
    22
    23
    24
    25
    26
    27
    28
    29
     
    #! /usr/bin/perl
    %liste = ();
    use Digest::MD5 qw(md5_hex);
    my $file = 'list.txt';
    open my $info, $file or die "Could not open $file: $!";
    while( my $line = <$info>)  
    {   
    	$line =~ s/\r|\n//g;
    	my $md5 = md5_hex($line);
    	my $add = substr $md5,0,1;
    	my $add2 = substr $md5,1,3;
    	my $add3 = substr $md5,4,3;
    	$key = "hash__/".$add."/".$add2.".txt";
    	my $toprint = $add3."\n".$line."\n"; 
     
    	push @{$liste{$key}}, $toprint;
    	$size = scalar(@{$liste{$key}});
    	if($size == 200)
    	{
            open (FILE, ">> $key") || die "problem opening $key\n";
    	for(my $j = 0;$j < 200;$j++)
    	{
    	print FILE $liste{$key}[$j];
    	}
    	delete($liste{$key});
    	close(FILE);
    	}
    }
    C'est mon premier script en perl, donc j'imagine que ça n'est pas du tout bien codé. J'ai remarqué du coup une nette amélioration en écriture, a peu près 80.000.000 de lignes en 45mn. Mais c'est toujours lent sachant qu'il me faut écrire pratiquement 4 milliards de lignes.

    Est-ce que vous verriez des optimisations à apporter pour améliorer la vitesse d'écriture ? J'ai choisi un buffer de 200 lignes complètement arbitrairement, peut-être qu'un buffer plus gros serait mieux ?
    Le fichier list.txt fait 45Go, ça vient peut être de là ?

    Merci

  8. #8
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    globalement, c'est plutôt pas mal écrit. Quelques points cependant:

    Sur le codage:

    Première suggestion (quasi obligatoire): les bonnes pratiques actuelles exigent que tu ajoutes les deux pragmas (directives de compilation) suivants à tout script de plus d'une ligne (à mettre au tout début du code, juste après #! /usr/bin/perl) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    use strict;
    use warnings;
    Cela demande au compilateur de vérifier ton code de façon bien plus détaillée et à te signaler des erreurs ou constructions potentiellement dangereuses. Par exemple, ça te signalera une éventuelle faute de frappe sur le nom d'une variable, et plein d'autres choses.

    Cela te donnera peut-être de nouvelles erreurs à corriger et t'ennuiera peut-être dans un premier temps, mais ça en vaut vraiment la peine.

    Deuxième point important: indente-ton code de façon cohérente pour refléter le flux de contrôle. Cela t'aidera vraiment à comprendre la structure quand tu voudras modifier dans 3 mois.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    open my $info, $file or die "Could not open $file: $!";
    Par défaut, un fichier est ouvert en lecture, mais c'est préférable de le dire explicitement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    open my $info, "<", $file or die "Could not open $file: $!";
    Bien que cela ne puisse en principe pas arriver dans ton script tel qu'il est actuellement, il est souvent préférable d'écrire dans un tel cas:
    Comme ça, si une péripétie du code loupe le 200 pile, au moins tu ne continue pas indéfiniment à remplir le tableau concerné.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    open (FILE, ">> $key") || die "problem opening $key\n";
    Version plus idiomatique:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    open my $FILE, ">>", "$key" or "problem opening $key $!";

    Sur les perf:

    Pas grand chose malheureusement.

    Plutôt que de recompter les lignes de tes tableaux à chaque fois, il serait sans doute plus rapide de maintenir un compteur pour chaque fichier, par exemple avec un hash de compteurs. Mais le gain restera assez marginal, je pense.

    Question plus importante: combien as-tu de fichiers de sortie? Si tu n'en as que quelques-uns, il serait préférable de garder les fichiers de sortie ouverts, plutôt que de les ouvrir à chaque fois (une ouverture de fichier est assez pénalisante). Cela compliquera un peu le code (il faut garder plusioeurs file handles oyuverts et choisir le bon à chaque fois), aussi je ne te dirai comment faire que si le nombre est assez faible. A défaut, oui, augmenter la taille du buffer améliorera les choses, puisque ça réduira la pénalité associée aux ouvertures multiples de fichiers de sortie.

    Cela dit, 45 GO et 4 milliards de lignes, n'espère pas faire cela en 3 minutes...

    En laissant de côté pour l'instant l'idée de garder plusieurs files handles de sortie ouverts en même temps, voici la version de code que je proposerai (pas testée, bien sûr, je n'ai pas de données):
    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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
     
    #! /usr/bin/perl
    use strict;
    use warnings;
     
    my %liste ;
    use Digest::MD5 qw(md5_hex);
    my $in_file = 'list.txt'; # variable plus parlante
    my %line_count; # compteurs de lignes
    open my $info, "<", $in_file or die "Could not open $infile: $!";
    while( my $line = <$info>)  
    {   
        $line =~ s/[\r\n]+//g; # sans doute très légèrement plus rapide, et plus sûr
        my $md5 = md5_hex($line);
        my $add = substr $md5,0,1;
        my $add2 = substr $md5,1,3;
        my $add3 = substr $md5,4,3;
        my $key = "hash__/".$add."/".$add2.".txt";
        my $toprint = $add3."\n".$line."\n"; 
     
        push @{$liste{$key}}, $toprint;
        $line_count{$key}++;
        # $size = scalar(@{$liste{$key}});
        if($line_count{$key} >= 1000) { # tentative à l'aveugle d'augmentation du buffer, 
                                        # la taille à choisir dépendra du nombre de fichiers de sortie 
                                        # (donc du nombre de buffers)
            open my $FILE, ">>", $key or die "problem opening $key $!";
            for my $item (@{$liste{key}}) { # syntaxe un chouia plus rapide, et plus lisible
                print $FILE $item;
            }
            delete($liste{$key});
            $line_count{$key} = 0; # remettre à 0 le compteur
            close($FILE);
        }
    }
    Voilà, j'espère que ça aide.

    J'ajoute qu'il faudra prévoir de vider les buffers en cours à la fin du traitement.

    Si ton nombre de fichiers de sortie est raisonnable, je pourrai te montrer comment les garder ouverts.

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 69
    Points : 34
    Points
    34
    Par défaut
    Merci pour cette réponse très détaillée. Je ferais ce midi les modifications de syntaxe.

    Suite à mon précédent message j'ai apporté quelques modifications. Déjà j'ai mis un buffer de 800 lignes, ce qui me mange 90% de ram.
    Ensuite j'ai remplacé la regex sur la variable line par un chomp, je ne sais pas si c'est plus rapide.
    Pour finir j'ai supprimé ma boucle for pour la remplacer par un print FILE values($liste{$key});. Pareil je ne sais pas si c'est plus rapide mais ça tourne, je verrais ce que ça donne.

    Pour les fichiers de sortie, il y en a 65536, puisque il y a quatre variables de 16 valeurs possible. J'avais pensé à laisser ouvert, mais je ne sais pas si c'est trop.

    EDIT : Bon il se trouve qu'avec un buffer plus grand c'est - beaucoup - plus lent, je ne sais pas pourquoi.

  10. #10
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Un chomp est mieux si tu as la certitude que le fichier est au format de la plateforme sur laquelle tu exécutes ton programme. Sans doute un peu plus rapide, mais tu ne verras pas de différence significative.

    La regex est mieux seulement si ton fichier vient par exemple de Windows et que tu travailles sous Unix, ou le contraire.

    Je ne pense pas que le remplacement de la boucle for change grand chose, mais pourquoi pas?

    Un un certain point, la seule manière de réellement optimiser les performances est de commencer par profiler le code, c'est à dire dé trouver où il passe beaucoup de temps. L'outil absolu pour profiler du code Perl, c'est NYTProf. Pour chaque ligne de code, il te dit combine de fois elle a été exécutée, combien de temps elle a pris, et ainsi de suite.

    Par exemple, si tu découvres que le script passe 90% de son temps dans la ligne (juste une hypothèse pour la discussion):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    my $md5 = md5_hex($line);
    ça ne sert en gros à rien d'optimiser le reste, le gain sera au mieux de 10% (en fait nettement moins), du moins tant que tu n'auras pas trouver un éventuel moyen d'optimiser cette ligne particulière.

    Sinon, avec 65-k fichiers, je doute que l'on puisse les laisser tous ouverts, l'OS ne supportera sans doute pas autant de file handles ouverts en mêm temps.

  11. #11
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 69
    Points : 34
    Points
    34
    Par défaut
    J'utiliserais l'outil pour profiler mon code. Pour le moment il tourne, j'ai mis un buffer de 400, et ça avance beaucoup plus vite qu'avec 200 ou 800, pour le moment ça tourne a 300+ millions de lignes par heure.

    Le code final :

    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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
     
    #! /usr/bin/perl
    use strict;
    use warnings;
     
    my %liste ;
    use Digest::MD5 qw(md5_hex);
    my $infile = 'wordlist_finale_u'; # variable plus parlante
    my %line_count; # compteurs de lignes
    open my $info, "<", $infile or die "Could not open $infile: $!";
    while( my $line = <$info>)  
    {   
        chomp($line);
        my $md5 = md5_hex($line);
        my $add = substr $md5,0,1;
        my $add2 = substr $md5,1,3;
        my $add3 = substr $md5,4,3;
        my $key = "md5hash__/".$add."/md5".$add2.".txt";
        my $toprint = $add3."\n".$line."\n"; 
     
        push @{$liste{$key}}, $toprint;
        $line_count{$key}++;
        if($line_count{$key} >= 400) { # tentative à l'aveugle d'augmentation du buffer, 
     
            open my $FILE, ">>", $key or die "problem opening $key $!";
            print $FILE values($liste{$key});
            delete($liste{$key});
            $line_count{$key} = 0; # remettre à 0 le compteur
            close($FILE);
        }
    }
    Je vais essayer de profiler le code pour voir.

  12. #12
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    OK, bien, j'ai bien une ou deux idées de petites optimisations supplémentaires, mais ça ne sert à rien d'y réfléchir tant qu'on n'a pas le résultat du profilage.

  13. #13
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 69
    Points : 34
    Points
    34
    Par défaut
    Bon, il se trouve qu'il y a un rendement bien décroissant pour la vitesse de mon script, au final j'en suis à peine a 350.000.000 en 5h ... Le 300 millions par heure que j'avais avancé était juste une extrapolation par rapport aux premières dix minutes.

    Quelles sont les optimisations dont vous aviez idée ? A ce rythme, il me faudra entre 50 et 60h pour finir le fichier, pour le md5 ça passera, mais si je peux optimiser ça pour le sha1 et les autres ça m'arrange.

  14. #14
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 820
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 820
    Points : 499 184
    Points
    499 184
    Par défaut
    Bonjour,
    De toute façon, la première optimisation n'est pas au niveau du programme ou du langage dans ce genre de problématique. Étant donné qu'il y a beaucoup d'accès disque, la première limite est le disque lui même et là on ne peut rien pour toi.

  15. #15
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par ganon551 Voir le message
    Quelles sont les optimisations dont vous aviez idée ? A ce rythme, il me faudra entre 50 et 60h pour finir le fichier, pour le md5 ça passera, mais si je peux optimiser ça pour le sha1 et les autres ça m'arrange.
    Des micro-optimisations sur du code qui est peut-être bien assez rapide ne servent à rien si c'est ailleurs que le programme passe beaucoup de temps. Profiler le programme est la priorité.

Discussions similaires

  1. trait en dessous de chaque ligne d'un tableau
    Par auduma dans le forum Balisage (X)HTML et validation W3C
    Réponses: 7
    Dernier message: 14/04/2005, 13h51
  2. [CR] Entête de tableau à chaque page, et tableau...
    Par titelle dans le forum SAP Crystal Reports
    Réponses: 6
    Dernier message: 15/04/2004, 09h13
  3. Tableau d'éléments de type variable
    Par Drooxy dans le forum Langage
    Réponses: 4
    Dernier message: 16/03/2003, 15h20
  4. Supprimer un élément d'un tableau
    Par CaptainChoc dans le forum Langage
    Réponses: 15
    Dernier message: 23/12/2002, 23h14
  5. Réponses: 3
    Dernier message: 16/12/2002, 16h12

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