GNU/Linux >> Znalost Linux >  >> Linux

Cpu je zdarma, ale Bash Script nevyužívá všechny zdroje CPU?

Spustil jsem jednoduchý skript pro vygenerování velkého (10000000 řádků) souboru csv se 6 poli, ve kterých se některá pole změnila v každém řádku/řádku, pomocí while smyčka. Stroj měl všech (32) CPU volných, spousta RAM (~31 Gb) byla také volná.

Skript jsem načasoval pomocí příkazu

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

Po asi 2 hodinách běhu jsem získal následující statistiky:

Časování příkazu:“bash script.01.sh”
Čas uživatele (v sekundách):1195,14
Systémový čas (v sekundách):819,71
Procento CPU, které tato úloha získala:27 %
Uplynulý čas (nástěnné hodiny) (h:mm:ss nebo m:ss):2:01:10
Průměrná velikost sdíleného textu (kbajty):0
Průměrná velikost nesdílených dat (kbajty ):0
Průměrná velikost zásobníku (kbajty):0
Průměrná celková velikost (kbajty):0
Maximální velikost rezidentní sady (kbajty):4976
Průměrná velikost rezidentní sady (kbajty) ):0
Hlavní chyby stránky (vyžadující vstup/výstup):0
Malé chyby stránky (obnovení rámce):3131983488
Dobrovolné přepnutí kontextu:22593141
Nedobrovolné přepnutí kontextu:10923348
Swaps:0
Vstupy systému souborů:0
Výstupy systému souborů:2182920
Odeslané zprávy soketu:0
Přijaté zprávy soketu:0
Doručené signály:0
Velikost stránky (bajtů):4096
Stav ukončení:0

Chci vědět, proč můj skript využíval pouze 27 % CPU? Disk IO nebyl vůbec nic moc (viz výstup vmstat). Co tedy omezení způsobilo? Kód ve skriptu?

Zde je skript:

#!/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  

Přijatá odpověď:

Pomocí strace , viděl jsem tu čáru

number=$(expr $number + 1)

způsobí rozvětvení, hledání cesty a exec expr . (Používám bash 4.2.45 na Ubuntu). Tato režie souborového systému, disku a procesu vedla k tomu, že bash získal pouze asi 28 % CPU.

Když jsem změnil tento řádek tak, aby používal pouze operace vestavěné do shellu

((number = number + 1))

bash využíval asi 98 % CPU a skript běžel za půl hodiny. Bylo to na jednoprocesorovém 1,5GHz Celeronu.

Skript jako takový nedělá nic, co běží paralelně, takže mít 32 volných CPU moc nepomůže. Určitě jej však můžete paralelizovat tak, že jej například rozdělíte do 10 smyček po 1 milion iterací, které běží paralelně, zapíšete do 10 různých souborů a poté použijete cat k jejich kombinaci.

Následující ukázkový program přidal @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. Jak ladit Bash skript?

  2. Bash Echo Příkazový řádek spuštěn na samotném příkazovém řádku (ne ve skriptu)?

  3. Bash skript pro odstranění všech souborů kromě N při abecedním řazení

  1. atomic create soubor, pokud neexistuje z bash skriptu

  2. Smažte všechny soubory kromě nejnovějších 3 v bash skriptu

  3. Spusťte příkaz bash na jenkins pipeline

  1. Proměnná Curl Outfile nefunguje ve skriptu Bash?

  2. Proč překladový soubor Bash neobsahuje všechny chybové texty?

  3. Shoda vzoru nefunguje ve skriptu bash