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 :

Optimisation d'un script Bash


Sujet :

Shell et commandes GNU

  1. #1
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2016
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2016
    Messages : 6
    Points : 2
    Points
    2
    Par défaut Optimisation d'un script Bash
    Bonjour !

    J'ai un script bash à optimiser, il s’exécute en 200 ms, il faudrait qu'il descende en dessous des 50 ms . Quand je parle de l'exécution, je veux parler d'un parcours total de la boucle While)

    J'ai beaucoup de mal à l'optimiser, connaissant mal ce langage.. Je sais par exemple qu'il faut limiter les appels extérieurs, mais difficile à mettre en pratique ^^

    Voici le 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
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    #!/bin/bash
    #
    ##### take_screenshot #####
    #
    # Permet de capture l'image d'un display
    #
    # Param 1 = Display
    # Param 2 = Token
    #
    *
    display=$1
    token=$2
    *
    counter=0
    is_closed=0
    errorCounter=0
    *
    import -display :$display -window "$token" ../tmp/$token.png > /dev/null
    cp ../tmp/$token.png ../tmp/import_$token.png
    cp ../tmp/$token.png ../tmp/import_$token"_tmp_1.png"
    *
    while [ $is_closed -eq 0 ]; do
    *
    #################################
    #
    # CAPTURE_FENETRE_PRINCIPALE
    #
    #################################
    *
    **#TEST DE FERMETURE DE LA FENETRE
    **retour=$(DISPLAY=:$display xdotool search --name "$token")
    *
    **if [ $retour -z ]
    **then
    ****if [ $errorCounter -ge 20 ]
    ****then
    *******is_closed=1
    *******./log.sh "log_flux.txt" "Fermeture brutale de $token survenue" &
    ****fi*
    ****errorCounter=$(($errorCounter+1))
    **else
    ****errorCounter=0
    **fi
    **#FIN DE TEST
    *
    **info=$(xwininfo -name "$token" -display :$display)
    **width_actu=$(echo $info | awk {'print $25'})
    **height_actu=$(echo $info | awk {'print $27'})
    *
    **offsetX=$(echo $info | awk {'print $11'})
    **offsetY=$(echo $info | awk {'print $15'})
    *
    **import -display :$display -screen -window root -crop $width_actu"x"$height_actu"+"$offsetX"+"$offsetY ../tmp/$token.png
    *
    **cp ../tmp/$token.png ../tmp/import_$token.png &
    **cp ../tmp/$token.png ../tmp/import_$token"_tmp_2.png" &
    *
    #################################
    #
    # CAPTURE_MULTI_FENETRAGE
    #
    #################################
    *
    ***window_list=$(./get_all_window.sh $token)
    *
    ***for word in $window_list
    ***do
    ******if [ "$word" != "$token" ]
    ******then
    *****#Si l'image root n'existe pas, on la créer
    *****if [ test -f ../tmp/import_$word"_tmp_1.png" ]
    *****then
    ********import -display :$display -window "$word" ../tmp/$word.png > /dev/null
    ********cp ../tmp/$word.png ../tmp/import_$word.png
    ********cp ../tmp/$word.png ../tmp/import_$word"_tmp_1.png"
    *****fi
    *
    *****info=$(xwininfo -name "$word" -display :$display)
    *****width_actu_child=$(echo $info | awk {'print $25'})
    *****height_actu_child=$(echo $info | awk {'print $27'})
    *
    *****offsetX_child=$(echo $info | awk {'print $11'})
    *****offsetY_child=$(echo $info | awk {'print $15'})
    *
    *****import -display :$display -window root -crop $width_actu_child"x"$height_actu_child"+"$offsetX_child"+"$offsetY_child ../tmp/$word.png > /dev/null
    *********cp ../tmp/$word.png ../tmp/import_$word.png &
    *****cp ../tmp/$word.png ../tmp/import_$word"_tmp_2.png" &
    ******fi
    ***done
    done
    Quelques conseils d'optimisations serait les bienvenues !

    En vous remerciant d'avance,

    Bonne journée

  2. #2
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 080
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 080
    Points : 30 778
    Points
    30 778
    Par défaut
    Dans le style d'appel externe que l'on peut éviter, c'est l'utilisation de awk là où un simple cut répondrait au besoin...
    Modérateur Langage SQL
    Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
    N'oubliez pas le bouton et pensez aux balises
    [code]
    Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
    Aide-toi et le forum t'aidera : Un problème exposé sans mentionner les tentatives de résolution infructueuses peut laisser supposer que le posteur attend qu'on fasse son travail à sa place... et ne donne pas envie d'y répondre.

  3. #3
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2016
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2016
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    Bonjour,

    Tout d'abord merci pour votre réponse !

    En effet, je vais remplacer les awk par des cut. Mise à part ce cas, comment savoir, de façon générale, quelle commande externe est la plus légère ? Ou peut être que cut est présent directement dans le build bash, contrairement à awk ?

    --

    Dans ce script, 75% du temps de traitement correspond à l'import d'imageMagick, qui représente 150ms. Je ne suis pas sur que cette ligne peut être améliorée..

    Je vais déjà commencer par remplacer les awk par des cut ! .

    Merci encore.

  4. #4
    Expert éminent Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 035
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 035
    Points : 8 400
    Points
    8 400
    Par défaut
    salut,

    déjà vouloir optimiser -en rapidité- du bash ça me semble relativement hérétique, bash est ce qui se fait de plus lent, particulièrement sur les boucles

    effectivement t'as 4x le même genre de ligne dans ton code du genre var=$(echo $machin | awk), ce qui fait spawn 4x awk pour rien, je te propose -et ça peut sûrement encore être amélioré- :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    read width_actu_child height_actu_child offsetX_child offsetY_child <<< "$(awk 'printf ("%s %s %s %s", $25, $27, $11, $15)' <<< "$info")"
    et si tu voulais complètement te passer des temps de création de processus, ben tu coderais le tout en Perl, en Python, voire carrément en C

    mais l'essentiel de ton traitement ne vient pas de bash, grosso modo ton code peut être perçu comme suit :
    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
    while
       xdotool
       ./log.sh
       xwininfo
       awk (x4)
       import
       cp (x2)
       ./get_all_window.sh
       for
          import
          cp (x2)
          xwininfo
          awk (x4)
          import
          cp (x2)
       done
    done
    à vue de nez je dirais :
    • qu'il faut se pencher également sur les deux autres scripts bash appelés (quel est leur impact ?)
    • qu'il y a beaucoup d'opérations disque, que tu auras du mal à optimiser, à moins de passer sur un ssd peut-être ? ^^
    • que le coupable idéal ce serait bien import, sur lequel tu n'as pas de contrôle non plus donc l'optimisation s'arrête ici possiblement
    • qu'in fine le mieux pour en avoir le coeur net serait encore de bencher/chronométrer chaque opération (en feintant comme expliqué ici par exemple)

  5. #5
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2016
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2016
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    Bonjour,

    Merci pour ton analyse .

    En effet déclarer qu'un seul awk me semble beaucoup mieux !

    --

    Je pensais également à me tourner vers le Python, ou peut être le dash, mais comme tu le disais, l'essentiel du temps de traitement vient de scripts externe, donc le bash peut surement convenir.

    J'avais déjà timé chaque instruction, et le import occupe 150 ms sur les 200 ms que prend une boucle complète.

    --

    Les scripts externes log.sh et get_all_windows.sh possède un temps de traitement négligeable ^^.

    Je pense que tu as raison, je pourrais peut être gagner quelque milliseconde, mais difficile de diviser le temps par deux, même en optimisant et en adoptant python ou perl, étant donné que le traitement vient de fichiers externes..

    Merci en tout cas .

  6. #6
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 266
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 266
    Points : 12 681
    Points
    12 681
    Par défaut
    Bonjour,

    Tu dois pouvoir gagner un peu de temps, si tu te passes de tout tes cp qui semble redondant et si tu fait tes imports en background et directement dans le fichier final qui semble être à chaque fois le dernier cp.
    En exemple, les lignes 18,19 et 20 deviendraient:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    import -display :$display -window "$token" ../tmp/import_$token"_tmp_1.png" > /dev/null &
    #cp ../tmp/$token.png ../tmp/import_$token.png
    #cp ../tmp/$token.png ../tmp/import_$token"_tmp_1.png"
    et avant de sortir de ton script, il faut juste rajouter la commande wait
    Cordialement.

  7. #7
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2016
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2016
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    Merci beaucoup, grâce à vos conseils, j'ai réussit à relativement bien réduire le temps d'exécution de mon script !

    J'aurais un second et dernier script à optimiser, beaucoup plus court ^^. Mais je vois difficilement comment y parvenir.. (J'ai déjà commencé à y travailler dessus, en appliquant vos conseils)

    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
    36
    37
    38
    39
    #!/bin/dash
    #
    ##### CLICK.SH #####
    #
    # Permet de simuler des clicks
    #
    # Param1 = Token
    # Param2 = X relatif
    # Param3 = Y relatif
    # Param4 = button {1:"left", 3:"right"}
    # Param3 = action {up, down, move}
    #
    *
    token=$1
    x=$2
    y=$3
    button=$4
    action=$5
    *
    cd script/
    display=$(./get_display_by_token.sh "$token")
    *
    info=$(xwininfo -name "$token" -display :$display)
    coord=$(echo $info | awk -v varx="$x" -v vary="$y" '{print $11+varx" "$15+vary}')
    *
    DISPLAY=:$display xdotool mousemove $coord
    *
    if [ $action -eq 1 ]
    then
    ***#mouse up
    ***DISPLAY=:$display xdotool mouseup $button &
    ***exit
    elif [ $action -eq 2 ]
    then
    ***#mouse down
    ***DISPLAY=:$display xdotool mousedown $button &
    ***exit
    fi
    exit
    Ce script s'exécute en 90ms environ, ce qui rajoute beaucoup de latence dans mon application.

    Si quelqu'un a des idées, je prends avec plaisir .

    Bonne journée !

  8. #8
    Expert éminent sénior Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 238
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 238
    Points : 13 443
    Points
    13 443
    Par défaut
    Bonjour

    Quand je veux créer un robot (même sous Linux lançable en émulateur console), j'utilise la classe java.awt.Robot qui peut lire à l'écran, bouger la souris, cliquer, taper au clavier ... En finalement assez peu de code.
    Par contre, c'est du java.
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  9. #9
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2016
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2016
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    Oui je connais cette classe, qui est plutôt pas mal oui !

    Mais dans ce cas ci, ce n'est pas vraiment un robot que je dois faire, je suis en stage, et je dois créer une application permettant d’exécuter un programme depuis le navigateur.
    Donc coté Linux je dois retranscrire les événements capté par le javascript. Tout marche, mais je rencontre quelques problèmes de latence, environ 300 ms sur tout le parcours (Entre le moment où l'on clic, et le moment où l'image change).

    Chaque programme est lancé sur un Display différent, donc je ne suis pas sur que je peux les atteindre en Java, si je passe par un émulateur ^^. Et ça risque de charger encore plus le processeur avec la JVM.

    --

    Merci en tout cas .

  10. #10
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 266
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 266
    Points : 12 681
    Points
    12 681
    Par défaut
    Pas sur que tu gagnes du temps car on ne sait pas ce qui est vraiment lent dans ton script, mais tu dois pouvoir par exemple simplifier:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    info=$(xwininfo -name "$token" -display :$display)
    coord=$(echo $info | awk -v varx="$x" -v vary="$y" '{print $11+varx" "$15+vary}')
    par quelque chose du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    coord=$(xwininfo -name "$token" -display :$display | awk -v varx="$x" -v vary="$y" '{XX=XX$0}END{$0=XX;print $11+varx" "$15+vary}')
    Cordialement.

  11. #11
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2016
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2016
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    Bonjour,

    Oui en effet j'ai oublié de vous parler des temps d'exécution, et c'est en effet ces deux lignes là qui possède un temps très très variable (Allant de quelques milliseconde à plus d'une centaine).

    Merci beaucoup pour ta nouvelle ligne, je gagne 30 ms en moyenne !! . Meme si je ne comprend pas trop la partie avec les "XX=XX$0", merci en tout cas .

  12. #12
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 266
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 266
    Points : 12 681
    Points
    12 681
    Par défaut
    La partie awk XX=XX$0 sert à remonter toute la sortie de xwininfo sur une seule ligne et une fois que toutes les lignes ont été traitées, je positionne $0 à XX pour ensuite récupérer les champs qui nous interressent.
    Cordialement.

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

Discussions similaires

  1. Requête POST dans un script bash
    Par desperado dans le forum Linux
    Réponses: 4
    Dernier message: 11/12/2007, 23h38
  2. Réponses: 21
    Dernier message: 29/09/2005, 20h33
  3. Script bash : Pb avec sed
    Par fred64 dans le forum Linux
    Réponses: 3
    Dernier message: 19/08/2005, 12h24
  4. Scripts bash : requêtes sql
    Par milka dans le forum Linux
    Réponses: 3
    Dernier message: 17/08/2005, 11h59
  5. Problème script Bash
    Par Sphost dans le forum Linux
    Réponses: 10
    Dernier message: 26/07/2005, 10h56

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