GNU/Linux >> Linux Esercitazione >  >> Linux

La CPU è gratuita, ma lo script Bash non utilizza tutte le risorse della CPU?

Ho eseguito un semplice script per generare un file CSV di grandi dimensioni (10000000 righe) con 6 campi in cui alcuni campi sono cambiati in ogni riga/riga, utilizzando un while ciclo continuo. La macchina aveva tutte le (32) CPU libere, anche molta RAM (~31 Gb).

Ho cronometrato lo script con il comando

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

Dopo aver eseguito per circa 2 ore, ho ottenuto le seguenti statistiche:

Comando a tempo:"bash script.01.sh"
Tempo utente (secondi):1195,14
Tempo di sistema (secondi):819,71
Percentuale di CPU ottenuta da questo lavoro:27%
Tempo trascorso (orologio da parete) (h:mm:ss o m:ss):2:01:10
Dimensione media del testo condiviso (kbyte):0
Dimensione media dei dati non condivisi (kbytes) ):0
Dimensione media dello stack (kbyte):0
Dimensione media totale (kbyte):0
Dimensione massima del set residente (kbyte):4976
Dimensione media del set residente (kbytes) ):0
Errori di pagina principali (che richiedono I/O):0
Errori di pagina minori (rivendicazione di un frame):3131983488
Cambiamenti di contesto volontari:22593141
Cambiamenti di contesto involontari:10923348
Swap:0
Input del file system:0
Output del file system:2182920
Messaggi socket inviati:0
Messaggi socket ricevuti:0
Segnali consegnati:0
Dimensione pagina (byte):4096
Stato uscita:0

Voglio sapere perché il mio script utilizzava solo il 27% della CPU? L'IO del disco non era affatto un granché (visto nell'output di vmstat). Quindi cosa ha causato la restrizione? Il codice nello script?

Ecco lo 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  

Risposta accettata:

Usando strace , ho visto che la linea

number=$(expr $number + 1)

provoca un fork, una ricerca del percorso e un exec di expr . (Sto usando bash 4.2.45 su Ubuntu). Quell'overhead di filesystem, disco e processo ha portato bash a ottenere solo il 28% circa della CPU.

Quando ho cambiato quella riga per usare solo le operazioni integrate della shell

((number = number + 1))

bash ha utilizzato circa il 98% della CPU e lo script è stato eseguito in mezz'ora. Questo era su un Celeron a CPU singola da 1,5 GHz.

Lo script così com'è non fa nulla che venga eseguito in parallelo, quindi avere 32 CPU libere non aiuterà molto. Tuttavia, puoi certamente parallelizzarlo, ad esempio, suddividendolo in 10 loop da 1 milione di iterazioni che vengono eseguiti in parallelo, scrivendo su 10 file diversi e quindi utilizzando cat per combinarli.

Il seguente programma di esempio è stato aggiunto da @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. Come eseguire il debug di uno script Bash?

  2. Il comando Rm nello script Bash non funziona con la variabile?

  3. Script Bash per eliminare tutti i file tranne N quando sono ordinati alfabeticamente

  4. file di creazione atomico se non esiste dallo script bash

  5. Elimina tutti i file tranne i 3 più recenti nello script bash

35 Esempi di script Bash

Come eseguire uno script Bash

Gui o un semplice script Bash per limitare la CPU?

Lo script Bash stampa Command Not Found su righe vuote

La corrispondenza del modello non funziona nello script bash

bash - rimuove tutte le directory (e i contenuti) ma non i file in pwd