GNU/Linux >> Tutoriels Linux >  >> Linux

Quel est le moyen le plus rapide d'exécuter un script ?

Les terminaux sont aujourd'hui plus lents qu'auparavant, principalement parce que les cartes graphiques ne se soucient plus de l'accélération 2D. Alors effectivement, imprimer sur un terminal peut ralentir un script, notamment lorsqu'il s'agit de scroller.

Par conséquent ./script.sh est plus lent que ./script.sh >script.log , qui à son tour est plus lent que /script.sh >/dev/null , car ces dernières impliquent moins de travail. Cependant, si cela fait suffisamment de différence pour un objectif pratique, cela dépend de la quantité de sortie produite par votre script et de sa rapidité. Si votre script écrit 3 lignes et se termine, ou s'il imprime 3 pages toutes les quelques heures, vous n'avez probablement pas besoin de vous soucier des redirections.

Modifier : Quelques repères rapides (et complètement cassés) :

  • Dans une console Linux, 240 x 75 :

    $ time (for i in {1..100000}; do echo $i 01234567890123456789012345678901234567890123456789; done)
    real    3m52.053s
    user    0m0.617s
    sys     3m51.442s
    
  • Dans un xterm , 260x78 :

    $ time (for i in {1..100000}; do echo $i 01234567890123456789012345678901234567890123456789; done)
    real    0m1.367s
    user    0m0.507s
    sys     0m0.104s
    
  • Rediriger vers un fichier, sur un disque Samsung SSD 850 PRO 512 Go :

     $ time (for i in {1..100000}; do echo $i 01234567890123456789012345678901234567890123456789; done >file)
     real    0m0.532s
     user    0m0.464s
     sys     0m0.068s
    
  • Rediriger vers /dev/null :

     $ time (for i in {1..100000}; do echo $i 01234567890123456789012345678901234567890123456789; done >/dev/null)
     real    0m0.448s
     user    0m0.432s
     sys     0m0.016s
    

J'aurais instinctivement été d'accord avec la réponse de Satō Katsura; Ca a du sens. Cependant, il est assez facile à tester.

J'ai testé l'écriture d'un million de lignes à l'écran, l'écriture (ajout) dans un fichier et la redirection vers /dev/null . J'ai testé chacun d'eux à tour de rôle, puis j'ai fait cinq répétitions. Ce sont les commandes que j'ai utilisées.

$ time (for i in {1..1000000}; do echo foo; done)
$ time (for i in {1..1000000}; do echo foo; done > /tmp/file.log) 
$ time (for i in {1..1000000}; do echo foo; done > /dev/null)

J'ai ensuite tracé les temps totaux ci-dessous.

Comme vous pouvez le voir, les présomptions de Satō Katsura étaient correctes. Selon la réponse de Satō Katsura, je doute également que le facteur limitant soit la sortie, il est donc peu probable que le choix de la sortie ait un effet substantiel sur la vitesse globale du script.

FWIW, ma réponse d'origine avait un code différent, qui avait le fichier ajouté et /dev/null rediriger à l'intérieur la boucle.

$ rm /tmp/file.log; touch /tmp/file.log; time (for i in {1..1000000}; do echo foo >> /tmp/file.log; done) 
$ time (for i in {1..1000000}; do echo foo > /dev/null; done)

Comme le souligne John Kugelman dans les commentaires, cela ajoute beaucoup de frais généraux. Dans l'état actuel de la question, ce n'est pas vraiment la bonne façon de le tester, mais je vais le laisser ici car il montre clairement le coût de la réouverture d'un fichier à plusieurs reprises depuis l'intérieur le script lui-même.

Dans ce cas, les résultats sont inversés.


Une autre façon d'accélérer un script consiste à utiliser un interpréteur de shell plus rapide. Comparez les vitesses d'un POSIX boucle occupée, exécutée sous bash v4.4 , ksh v93u+20120801 , et dash v0.5.8 .

  1. bash :

    time echo 'n=0;while [ $n -lt 1000000 ] ; do \
                      echo $((n*n*n*n*n*n*n)) ; n=$((n+1)); 
                   done' | bash -s > /dev/null
    

    Sortie :

    real    0m25.146s
    user    0m24.814s
    sys 0m0.272s
    
  2. ksh :

    time echo 'n=0;while [ $n -lt 1000000 ] ; do \
                      echo $((n*n*n*n*n*n*n)) ; n=$((n+1)); 
                   done' | ksh -s > /dev/null
    

    Sortie :

    real    0m11.767s
    user    0m11.615s
    sys 0m0.010s
    
  3. dash :

    time echo 'n=0;while [ $n -lt 1000000 ] ; do \
                      echo $((n*n*n*n*n*n*n)) ; n=$((n+1)); 
                   done' | dash -s > /dev/null
    

    Sortie :

    real    0m4.886s
    user    0m4.690s
    sys 0m0.184s
    

Un sous-ensemble de commandes en bash et ksh sont rétrocompatibles avec toutes les commandes de dash . Un bash le script qui utilise uniquement les commandes de ce sous-ensemble devrait fonctionner avec dash .

Quelques bash les scripts qui utilisent de nouvelles fonctionnalités peuvent être convertis en un autre interpréteur. Si le bash le script s'appuie fortement sur les nouvelles fonctionnalités, cela n'en vaut peut-être pas la peine -- certains nouveau bash les fonctionnalités sont des améliorations qui sont à la fois plus faciles à coder et plus efficace, (malgré bash étant généralement plus lent), de sorte que le dash équivalent, (qui peut impliquer l'exécution de plusieurs autres commandes), serait plus lent.

En cas de doute, faites un test...


Linux
  1. Qu'est-ce que Echo $ ? Faire??

  2. Le moyen le plus rapide d'extraire un iso ?

  3. À quoi sert le Colon Builtin ':' ?

  4. Quelle est la bonne façon d'utiliser inotify ?

  5. Quelle est la bonne façon d'insérer un onglet dans sed?

La "bonne" façon de tester si un service s'exécute dans un script ?

Exécuter à nouveau le script si l'entrée est Oui ?

Comment faire en sorte qu'un script shell s'exécute toujours en tant que root ?

Quelle est la meilleure façon de s'assurer qu'une seule instance d'un script Bash est en cours d'exécution ?

À quoi sert $# dans Bash

Quel est le moyen le plus sûr et le plus portable d'invoquer le binaire echo ?