Pętle powłoki są powolne, a bash są najwolniejsze. Pociski nie są przeznaczone do wykonywania ciężkiej pracy w pętlach. Powłoki mają na celu uruchomienie kilku zewnętrznych, zoptymalizowanych procesów na partiach danych.
W każdym razie byłem ciekawy, jak porównują się pętle powłoki, więc zrobiłem mały test porównawczy:
#!/bin/bash
export IT=$((10**6))
echo POSIX:
for sh in dash bash ksh zsh; do
TIMEFORMAT="%RR %UU %SS $sh"
time $sh -c 'i=0; while [ "$IT" -gt "$i" ]; do i=$((i+1)); done'
done
echo C-LIKE:
for sh in bash ksh zsh; do
TIMEFORMAT="%RR %UU %SS $sh"
time $sh -c 'for ((i=0;i<IT;i++)); do :; done'
done
G=$((10**9))
TIMEFORMAT="%RR %UU %SS 1000*C"
echo 'int main(){ int i,sum; for(i=0;i<IT;i++) sum+=i; printf("%d\n", sum); return 0; }' |
gcc -include stdio.h -O3 -x c -DIT=$G -
time ./a.out
(
Szczegóły:
- Procesor: Intel (R) Core (TM) i5 CPU M 430 @ 2.27GHz
- ksh: wersja sh (AT&T Research) 93u + 01.08.2012
- bash: GNU bash, wersja 4.3.11 (1) -release (x86_64-pc-linux-gnu)
- zsh: zsh 5.2 (x86_64-unknown-linux-gnu)
- myślnik: 0,5,7-4ubuntu1
)
(Skrócone) wyniki (czas na iterację) to:
POSIX:
5.8 µs dash
8.5 µs ksh
14.6 µs zsh
22.6 µs bash
C-LIKE:
2.7 µs ksh
5.8 µs zsh
11.7 µs bash
C:
0.4 ns C
Z wyników:
Jeśli chcesz nieco szybszej pętli powłoki, to jeśli masz [[
składnię i potrzebujesz szybkiej pętli powłoki, jesteś w zaawansowanej powłoce i masz również C-for for loop. Następnie użyj pętli C jak dla. Mogą być około 2 razy szybsze niż while [
pętle w tej samej skorupie.
- ksh ma najszybszą
for (
pętlę około 2,7 µs na iterację
- dash ma najszybszą
while [
pętlę około 5,8 µs na iterację
C dla pętli może być o 3-4 rzędy dziesiętne wielkości szybsze. (Słyszałem, że Torvaldowie kochają C).
Zoptymalizowana pętla C dla pętli jest 56500 razy szybsza niż while [
pętla bash (najwolniejsza pętla powłoki) i 6750 razy szybsza niż pętla kshfor (
pętla (najszybsza pętla powłoki).
Ponownie powolność powłok nie powinna mieć większego znaczenia, ponieważ typowym wzorem dla powłok jest odciążenie kilku procesów zewnętrznych, zoptymalizowanych programów.
Przy takim wzorcu powłoki często znacznie ułatwiają pisanie skryptów o wydajności przewyższającej skrypty Pythona (ostatnim razem, gdy sprawdzałem, tworzenie potoków procesu w Pythonie było dość niezdarne).
Kolejną rzeczą do rozważenia jest czas uruchamiania.
time python3 -c ' '
trwa 30 do 40 ms na moim komputerze, podczas gdy pociski trwają około 3 ms. Jeśli uruchamiasz wiele skryptów, szybko się to sumuje i możesz zrobić bardzo dużo w dodatkowych 27-37 ms, których uruchomienie zajmuje Python. Małe skrypty można ukończyć kilka razy w tym czasie.
(NodeJs jest prawdopodobnie najgorszym środowiskiem uruchomieniowym skryptów w tym dziale, ponieważ jego uruchomienie zajmuje około 100 ms (chociaż po jego uruchomieniu trudno byłoby znaleźć lepszą wydajność wśród języków skryptowych)).