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

Shell et commandes GNU Discussion :

"Cat" est trop lent (Windows)


Sujet :

Shell et commandes GNU

  1. #1
    Membre régulier
    Inscrit en
    Septembre 2006
    Messages
    365
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 365
    Points : 83
    Points
    83
    Par défaut "Cat" est trop lent (Windows)
    Bonjour,

    je suis en train d'executer une simple commande de concatenation de fichier:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for file in `ls *.logic`
        do
            cat $file >> final.logic
        done
    Ce code la prend exactement 5 secondes sur une machine Linux, 1min15 sur une machine Windows XP (RAM 3.5G), et 3min30 sur une machine Windows 7 (bien que plus puissante: RAM 8G)

    J'ai essaye de remplacer la commande cat par : type, ou awk mais j'ai toujours pratiquement les meme temps d'execution.

    Je n'ai rien trouve sur le net qui explique la difference qui peut y avoir entre l'utilisation de cat dans des SE differents.

    Qqn a une idee SVP?
    ou au moins une solution pour avoir une performance quasi egale entre Linux et windows?

    Merci

  2. #2
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 585
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 585
    Points : 19 462
    Points
    19 462
    Par défaut
    pourquoi faire une boucle, qui lancera autant de cat qu'il y a de fichiers ?

    le but de cat est justement de concaténer le contenu de fichers, donc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cat *.logic >> final.logic
    et puis, on ne fait pas for item in $(command); surtout pas ls. parce que

  3. #3
    Expert éminent sénior Avatar de frp31
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Juillet 2006
    Messages
    5 196
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Juillet 2006
    Messages : 5 196
    Points : 12 264
    Points
    12 264
    Par défaut
    Citation Envoyé par freestyler Voir le message
    Bonjour,

    Ce code la prend exactement 5 secondes sur une machine Linux, 1min15 sur une machine Windows XP (RAM 3.5G), et 3min30 sur une machine Windows 7 (bien que plus puissante: RAM 8G)

    Merci
    plus puisssant pas vraiment
    pour info la ram ne represente que la quantité de données qui peut y etre stockée sans avoir a faire des copies depuis/vers le disque qui est un périphérique mécanique et par concequent lent.

    deplus 8G de ram lente freinera plus le ressenti que 4 ou meme 2 rapide

    La quantité de ram n'accelere que tres tres tres peu le ressenti utilisateur.
    la comparaisent en seconde est pertinante mais pas la suite de la phrase

    Pour le reste j'allais faire la meme remarque que N_BaH, qui a tout a fait raison

  4. #4
    Membre régulier
    Inscrit en
    Septembre 2006
    Messages
    365
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 365
    Points : 83
    Points
    83
    Par défaut
    En fait j'essayais de reduire la question a l'essentiel..
    En fait voici mon code:
    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
            for file in `ls *.logic`
            do
     
                tmp_ext=`grep $(basename $file) list.external`
                if [[ ! -z $tmp_ext ]]; then  
                    cat $file >> external.logic
                    echo >> external.logic
                else            
                    tmp_exc=`grep $(basename $file) list.exclude`
                    if [[ -z $tmp_exc ]]; then
                        cat $file >> final.logic
                        echo >> final.logic
                    fi
                fi
            done
    Ceci explique l'usage de la boucle..

    Par contre, aucun d'entre vous n'a souleve le probleme de la difference des temps d'execution entre SE, qui est la source meme du probleme..

  5. #5
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 585
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 585
    Points : 19 462
    Points
    19 462
    Par défaut
    Par contre, aucun d'entre vous n'a souleve le probleme de la difference des temps d'execution entre SE, qui est la source meme du probleme..
    Désolé, je n'utilise pas Windows.
    Code bash : 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
            for file in `ls *.logic`
            for file in *.logic
            do
                tmp_ext=`grep $(basename $file) list.external`
                if [[ ! -z $tmp_ext ]] #ah, bah, non alors ! pas une double négation !
                #if [[ -n $tmp_ext ]]
                if grep "${file##*/}" list.external >/dev/null 2>&1
                then  
                    cat "$file" - >> external.logic
                    echo >> external.logic
                   extFiles+=( "$file" )
                else            
    # la condition opposée est implicite avec le else
                    tmp_exc=`grep $(basename $file) list.exclude`
                    if [[ -z $tmp_exc ]]; then
                        cat "$file" - >> final.logic
                        echo >> final.logic
                    fi
                    finalFiles+=( "$file" )
                fi
            done
    cat "${extFiles[@]}" >> external.logic
    cat "${finalFiles[@]}" >> final.logic

  6. #6
    Membre chevronné

    Homme Profil pro
    Responsable projets techniques
    Inscrit en
    Février 2003
    Messages
    980
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Responsable projets techniques
    Secteur : Biens de consommation

    Informations forums :
    Inscription : Février 2003
    Messages : 980
    Points : 1 894
    Points
    1 894
    Par défaut
    j'adore les réponses de N_BaH

    sinon, pour les problèmes de temps de réponse (qui ne sont pas forcément à l'origine du problème), tu utilises quoi sous Windows ? Cygwin ou les versions Windows des coreutils ?

  7. #7
    Membre régulier
    Inscrit en
    Septembre 2006
    Messages
    365
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 365
    Points : 83
    Points
    83
    Par défaut
    Cygwin.

    J'ai aussi essayé d'utiliser Windows Coreutils seulement mais j'ai toujours eu les mêmes problèmes..

  8. #8
    Membre régulier
    Inscrit en
    Septembre 2006
    Messages
    365
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 365
    Points : 83
    Points
    83
    Par défaut
    Quelqu'un a-t-il fait le test au moins?

    Ca me semble pourtant un post valide parce que les écarts entre Linux et Windows sont énormes. Et encore, meme entre Win7 et WinXP.

    J'ai beau cherché sur le net mais je n'ai trouvé aucune information sur le sujet..

  9. #9
    Membre chevronné

    Homme Profil pro
    Responsable projets techniques
    Inscrit en
    Février 2003
    Messages
    980
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Responsable projets techniques
    Secteur : Biens de consommation

    Informations forums :
    Inscription : Février 2003
    Messages : 980
    Points : 1 894
    Points
    1 894
    Par défaut
    Quelle volumétrie tu as ?

    Je viens de faire un test sur un bête PC sous Windows XP (X2 2GHz avec 2Go de RAM) sur 152 Mo et 284 fichiers .txt et ça prend genre 5 secondes; sur 840 Mo et 19 fichiers .dsx (c'est comme des fichiers textes), ça a pris 40 secondes...

    Les tests :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    d:\temp\>cat *.txt >> test001
    d:\temp\>cat *.dsx >> test002
    Les temps sont mesurés à la mimine mais bon, ça me paraît pas énorme comme temps...

    Donc à mon avis, soit c'est le reste de ton algo qui faisait perdre du temps, soit c'est cygwin quand tu utilises cygwin... dans tous les cas, difficile de répondre vu qu'il manque pleins d'informations (en vrac) :
    le test sous Linux, tu l'as fait sur la même machine ? Parce que tu parles de la RAM, mais pour cat seul, on s'en fiche : pour info, lors de mon test, cat a pris mois de 2 Mo de RAM ! Par contre, si tu as un disque en 10k rpm en raid 0 sous Linux et un vieux disque pata sous Windows, ça va plus jouer !
    ton disque Windows n'est pas fragmenté ?
    quelle est exactement la commande que tu compares : le script complet ou juste le cat ? Avec ou sans la boucle for ? etc...

  10. #10
    Membre régulier
    Inscrit en
    Septembre 2006
    Messages
    365
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 365
    Points : 83
    Points
    83
    Par défaut
    Bon après de multiples tests, il s'est avéré que le temps varie à cause de l'usage de la boucle for pour cat.

    Donc, capturer la liste dans une variable et faire : réduit le temps d'exécution d'une manière très évidente.

    Par contre, cela me fait revenir au problème initial auquel j'ai du écrire une boucle pour : c'est la nécessite d'ajouter unes ligne vide à la fin de chaque fichier pour avoir une concaténation acceptable.
    Si fichierA ne contient pas de retour chariot à la fin, alors la dernière ligne de fichierA et la première ligne de fichierB seraient sur la même ligne si on fait:
    Y a aucune option de cat qui fait ceci.
    Et j'ai beau cherché… une boucle s'impose ici. Ya t il une alternative?

    Merci beaucoup

  11. #11
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 585
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 585
    Points : 19 462
    Points
    19 462
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #!/bin/bash
    
    for file in *.logic
    do if grep "${file##*/}" list.external >/dev/null 2>&1
       then extFiles+=( "$file" )
       else finalFiles+=( "$file" )
       fi
    #si la dernière ligne du fichier ne se termine pas par \n, on en ajoute un.
       [[ $(od -c <(tail -1 "$file")) == *\n ]] || printf $'\n' >> "$file"
    done
    
    cat "${extFiles[@]}" >> external.logic
    cat "${finalFiles[@]}" >> final.logic
    ...
    ?

  12. #12
    Expert éminent

    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    1 946
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 1 946
    Points : 6 276
    Points
    6 276
    Par défaut
    Salut,

    Peut être une alternative avec "sed" :

    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
    $ cat A
    azerty
    qsdfg
    wxcvb$     # Pas de retour à la ligne ici
    $ cat B
    poiuy
    mlkjh
    nbvcx
    $ cat A B
    azerty
    qsdfg
    wxcvbpoiuy     # Pas de séparation
    mlkjh
    nbvcx
    $ sed -n '/./p' A B
    azerty
    qsdfg
    wxcvb
    poiuy
    mlkjh
    nbvcx
    $


    Édit : Suffit amplement

Discussions similaires

  1. la vitesse est trop lente
    Par stéphanie123 dans le forum Macros et VBA Excel
    Réponses: 8
    Dernier message: 22/05/2008, 13h43
  2. PHP 5 est trop lent.
    Par raphpell dans le forum Langage
    Réponses: 1
    Dernier message: 05/02/2008, 21h24
  3. [HSQLDB] C'est trop lent
    Par Djobird dans le forum JDBC
    Réponses: 5
    Dernier message: 03/07/2007, 10h29

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