GNU/Linux >> Tutoriels Linux >  >> Linux

Le processeur est gratuit, mais le script Bash n'utilise pas toutes les ressources du processeur ?

J'ai exécuté un script simple pour générer un grand fichier csv (10000000 lignes) avec 6 champs dans lesquels certains champs ont changé dans chaque ligne/ligne, en utilisant un while boucle. La machine avait tous les (32) processeurs libres, beaucoup de RAM (~ 31 Go) étaient également libres.

J'ai chronométré le script avec la commande

/usr/bin/time -v script bash.01.sh

Après avoir couru pendant environ 2 heures, j'ai obtenu les statistiques suivantes :

Commande chronométrée :"bash script.01.sh"
Temps utilisateur (secondes) :1195,14
Temps système (secondes) :819,71
Pourcentage de CPU obtenu par cette tâche :27 %
Temps écoulé (horloge murale) (h:mm:ss ou m:ss) :2:01:10
Taille moyenne du texte partagé (Ko) :0
Taille moyenne des données non partagées (Ko ) :0
Taille moyenne de la pile (Ko) :0
Taille moyenne totale (Ko) :0
Taille maximale de l'ensemble résident (Ko) :4976
Taille moyenne de l'ensemble résident (Ko ) :0
Défauts de page majeurs (nécessitant des E/S) :0
Défauts de page mineurs (récupération d'une trame) :3131983488
Commutations de contexte volontaires :22593141
Commutations de contexte involontaires :10923348
Permutations :0
Entrées du système de fichiers :0
Sorties du système de fichiers :2182920
Messages de socket envoyés :0
Messages de socket reçus :0
Signaux délivrés :0
Taille de la page (octets) :4096
État de sortie :0

Je veux savoir pourquoi mon script n'a utilisé que 27 % du processeur ? Le disque IO n'était pas grand-chose (vu dans la sortie vmstat). Alors, qu'est-ce qui a causé la restriction? Le code dans le script ?

Voici le script :

#!/usr/bin/env bash
number=1

while [[ $number -lt 10000001 ]] ; do  
    fname="FirstName LastName $"
    lname=""  
    email="[email protected]"  
    password="1234567890"  
    altemail="[email protected]"  
    mobile="9876543210"      

    echo "$fname,$lname,$email,$password,$altemail,$mobile" >> /opt/list.csv
    number=$(expr $number + 1)  
done  

Réponse acceptée :

En utilisant strace , j'ai vu que la ligne

number=$(expr $number + 1)

provoque un fork, une recherche de chemin et un exec de expr . (J'utilise bash 4.2.45 sur Ubuntu). Cette surcharge de système de fichiers, de disque et de processus a conduit bash à n'obtenir qu'environ 28 % du processeur.

Quand j'ai changé cette ligne pour n'utiliser que les opérations intégrées du shell

((number = number + 1))

bash a utilisé environ 98% du CPU et le script s'est exécuté en une demi-heure. C'était sur un Celeron à 1,5 GHz à processeur unique.

Le script tel quel ne fait rien qui s'exécute en parallèle, donc avoir 32 processeurs libres n'aidera pas beaucoup. Cependant, vous pouvez certainement le paralléliser, par exemple, en le divisant en 10 boucles d'un million d'itérations qui s'exécutent en parallèle, en écrivant dans 10 fichiers différents, puis en utilisant cat pour les combiner.

L'exemple de programme suivant a été ajouté par @Arthur2e5 :

max=1000000 step=40000 tmp="$(mktemp -d)"
# Spawning. For loops make a bit more sense in a init-test-incr pattern.
for ((l = 0; l < max; l += step)); do (
    for ((n = l + 1, end = (step + l > max ? max : step + l);
      n <= end; n++)); do
        # Putting all those things into the `buf` line gives you a 1.8x speedup.
        fname="FirstName LastName \$"
        lname=""  
        email="[email protected]"  
        password="1234567890"  
        altemail="[email protected]"  
        mobile="9876543210"
        buf+="$fname,$lname,$email,$password,$altemail,$mobile"$'\n'
    done
    printf '%s\n' "$buf" > "$tmp/$l" ) &
done # spawning..
wait
# Merging. The filename order from globbing will be a mess,
# since we didn't format $l to some 0-prefixed numbers.
# Let's just do the loop again.
for ((l = 0; l < max; l += step)); do
    printf '%s\n' "$(<"$tmp/$l")" >> /opt/list.csv
done # merging..
rm -rf -- "$tmp" # cleanup

Linux
  1. Bash Echo La ligne de commande exécutée sur la ligne de commande elle-même (pas dans un script) ?

  2. La variable Curl Outfile ne fonctionne pas dans le script Bash ?

  3. Pourquoi le fichier de traduction Bash ne contient-il pas tous les textes d'erreur ?

  4. La commande Rm dans le script Bash ne fonctionne pas avec la variable ?

  5. Script bash pour supprimer tous les fichiers sauf N lorsqu'ils sont triés par ordre alphabétique

35 exemples de scripts bash

Comment exécuter un script bash

Gui ou simple script bash pour accélérer le processeur ?

La correspondance de modèle ne fonctionne pas dans le script bash

bash - supprime tous les répertoires (et contenus) mais pas les fichiers dans pwd

shebang ou pas shebang