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 :

variable spéciale $|


Sujet :

Langage Perl

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 45
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Par défaut variable spéciale $|
    Quand on doit récupérer beaucoup de données, est-il utile de mettre la variable $| à 1? Cela évite-il de saturer la mémoire?

    Quand on dit : $| : Si non nulle, force un flush après chaque opération de lecture ou d'écriture sur le filehandle courant.


    Dans un programme où on écrit sur plusieurs fichiers ainsi que sur l'écran, les filehandles courants sont donc les 2 fichiers? L'affichage à l'écran se fait progressivement, quand $| est mis à 1, l'écran est-il également considéré comme un filehandle?

    Est-il possible de remplir les fichiers au fur et à mesure mais que l'affichage à l'écran ne se fasse qu'à la fin?


    Merci pour votre aide,

  2. #2
    Membre chevronné Avatar de iblis
    Inscrit en
    Janvier 2007
    Messages
    510
    Détails du profil
    Informations personnelles :
    Âge : 59

    Informations forums :
    Inscription : Janvier 2007
    Messages : 510
    Par défaut
    Bonjour.

    Je te dis comment je vois la chose.

    Quand tu accèdes en lecture ou écriture à un fichier, Perl cache les données entre les accès successifs : il en met une partie dans un tampon avant de délivrer les données au destinataire (en gros toi, si tu lis, le système si tu écris), cela évite de multiplier les accès systèmes et donc optimise la performance.

    Dans certains cas, tu veux cependant que la lecture ou l'écriture se fasse sans cache : tout de suite. Dans ces cas là tu dois "débuffeuriser", "flusher", le descripteur de fichier courant. C'est ce qui se produit quand tu donnes une valeur entière positive à $|.

    Donc pour répondre à ta première question : cela n'évite pas vraiment de saturer la mémoire, ou indirectement seulement mais cela permet de réaliser les accès en lecture et écriture sur le descripteur de fichier sans médiation, au coup par coup et pas paquet par paquet. Avec le buffer tu minimises les accès système et y gagne en performance, c'est le comportement par défaut. En "débuffeurisant", tu augmentes les accès systèmes et perd en performance mais tu y gagnes en réactivité (au passage tu libères l'usage du cache mais à mon avis c'est accessoire).

    Je ne sais pas si je suis très clair. Tu peux trouver un exposé avec exemples dans perldoc -q flush.

  3. #3
    Membre éprouvé
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 45
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Par défaut
    Merci pour ta réponse.

    Que veux-tu dire par 'tu y gagnes en réactivité'?
    Qu'est-ce que le cache? Est-ce bien le fait qu'un paquet de données est stocké dans le buffer et donc 'est caché' provisoirement pour qu'ensuite les données soient renvoyées 1 par 1 au script? Y perd-t-on en réactivité parce que justement ce stockage préliminaire est une étape ajoutée?
    ... ces questions te paraitront peut-être triviales mais je n'ai qu'une vague idée de ce qu'est un buffer et ça reste floue pour moi.

    Le lien répond à ma seconde question.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
       1.  # long wait, then row of dots all at once
       2. while( <> ) {
       3. print ".";
       4. print "\n" unless ++$count % 50;
       5.
       6. #... expensive line processing operations
       7. }
    To get around this, you have to unbuffer the output filehandle, in this case, STDOUT . You can set the special variable $| to a true value (mnemonic: making your filehandles "piping hot"):
    L'écran STDOUT fait donc partie des filehandles de sortie.


    Merci pour ton aide,

  4. #4
    Membre expérimenté

    Profil pro
    Inscrit en
    Août 2009
    Messages
    156
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 156
    Par défaut
    Je confirme ce que dit Iblis,
    si tu mets autoflush, Perl écrit directement dans son filehandle à chaque instruction d'écriture.

    Par contre, encore une fois, tu peux soit:
    - laisser Perl gérer quand il veut écrire
    - le forcer à écrire à chaque instruction d'écriture.

    Si tu ne veux aficher ton résultat qu'à la toute fin, tu as intérêt à faire un truc du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
      # Sauvegarder STDOUT (l'écran)
      open( STDOUT, '<&SAVEDOUT' ) or die "$!";
      # "Logger" STDOUT pendant l'execution
      open(STDOUT, ">$file") or die("Can't open output: $!");
      open(STDERR, ">&STDOUT") or die("Can't open output for errors: $!");
     
      # En fin de programme, recuperer STDOUT
      open( STDOUT, '>&SAVEDOUT' ) or die "$!";
      # Et afficher ton log
    Je suis pas sûr de la partie "sauvegarde" du filehandle car ça j'ai jamais fait, donc c'est ptêt pas comme ç apour érécupérer" l'écran en fin de programme.

  5. #5
    Membre chevronné Avatar de iblis
    Inscrit en
    Janvier 2007
    Messages
    510
    Détails du profil
    Informations personnelles :
    Âge : 59

    Informations forums :
    Inscription : Janvier 2007
    Messages : 510
    Par défaut
    J'imagine que l'explication de 50Nio a éclairé un peu plus ta lanterne. Désolé si je ne suis pas très clair : j'ai du mal avec le vocabulaire informatique français (je n'utilise que l'anglais pour tout ce qui est technique ).

    Un cache ou buffer est une mémoire tampon dans laquelle un programme stocke des données temporairement. Dans le cas qui nous concerne, Perl, comme je te l'ai dit, cache les accès au descripteur de fichier (filehandle) courant. Comme les exemples le montrent, c'est pour éviter que les accès système répétés handicape les perfomances : si, quand tu parses un fichier ligne à ligne, tu dois faire 100 000 appels système pour lire cent mille lignes, cela risque de te ralentir drôlement.

    (Un autre usage fréquent du cache est d'éviter de calculer – c'est à dire là encore d'obtenir des données dont l'obtention à un coût élevé – qui ont déjà été calculées : c'est le memoization bien décrit dans High-Order Perl, que si je me rappelle bien on lisait au même moment )

    Mais dans certains cas, tu veux que les lectures et/ou écritures se fassent tout de suite – ce que j'ai maladroitement appelé réactivité. As-tu regardé Suffering from buffering en lien dans perldoc, les exemples (repris en partie dans perldoc) sont très parlants.

    Le flush (libération et désactivation du buffer) n'est fait que sur le descripteur courant, d'où le jeu avec select().

    Pour en revenir à tes questions (pratiques) de départ.

    Oui STDOUT (par défaut ton "terminal") est un filehandle (ou plutôt est accéder par un filehandle). Donc par défaut Perl "cache" ("temporise") ce que tu écris sur ce descripteur de fichier. D'où une sorte de délai dans certains cas. C'est donc pour y circonvenir que tu fais un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    select STDOUT # pas nécessaire car c'est le filehandle de sortie courant par défaut
                  # et que par défaut $| = 1 débufurise la sortie
    $|++
    Est-il possible de remplir les fichiers au fur et à mesure mais que l'affichage à l'écran ne se fasse qu'à la fin?
    Oui, bien sûr comme tu l'as compris j'imagine. Tu ne change $| que pour le descripteur de fichier de sortie du fichier de log par exemple et STDOUT reste bufferisé.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    my $old_fh = select $log;
    $| = 1;
    print $log $data; # "hot" = pas de tampon
    select $old_fh; # on revient au descripteur de sortie par défaut (avec buffer, si on n'avait rien changé)
    Je ne sais pas si j'ai répondu à toutes tes questions. Sûrement les pros ici rajouteront ce qui manque.

  6. #6
    Membre expérimenté

    Profil pro
    Inscrit en
    Août 2009
    Messages
    156
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 156
    Par défaut
    Si tu as plusieurs filehandles, tu peux aussi setter autoflush comme ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
        use IO::File;
        autoflush STDOUT 1;
    ou
        STDOUT->autoflush(1);
    pour gérer autoflush pour chaque filehandle séparément.

    Je te rassure Iblis tes explications me semblent plutôt bien. :-)

  7. #7
    Membre éprouvé
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 45
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Par défaut
    Merci beaucoup pour vos explications si bien détaillées. Cela reste un peu floue car je manque de pratique. Je vais tester vos idées dans mes prochains scripts afin de mieux comprendre.

Discussions similaires

  1. Un caractere spécial % dans une macro-variable
    Par july1012 dans le forum Macro
    Réponses: 2
    Dernier message: 03/10/2012, 18h06
  2. insérer caractère spéciale dans variable
    Par Korben-Dallas dans le forum Débuter
    Réponses: 2
    Dernier message: 08/05/2011, 16h03
  3. remplacement d'un caractère spécial d'une variable
    Par ajor dans le forum Servlets/JSP
    Réponses: 1
    Dernier message: 22/04/2010, 14h54
  4. windows opener // nom variable spécial ( id[6] )
    Par rpatruno dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 16/04/2008, 22h54
  5. windows opener // nom variable spécial ( id[6] )
    Par rpatruno dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 07/04/2008, 11h28

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