SHELL SEQ:
Provavelmente, um meio útil de avaliar o desempenho de um shell é fazer várias avaliações simples e pequenas repetitivamente. É importante, penso eu, não apenas fazer um loop, mas fazer um loop por entrada , porque um shell precisa ler <&0
.
Eu pensei que isso complementaria os testes @cuonglm já postados porque demonstra o desempenho de um único processo de shell quando invocado , ao contrário do que demonstra a rapidez com que um processo shell é carregado quando invocado. Desta forma, entre nós, cobrimos os dois lados da moeda.
Aqui está uma função para facilitar a demonstração:
sh_bench() ( #dont copy+paste comments
o=-c sh=$(command -v "$1") ; shift #get shell $PATH; toss $1
[ -z "${sh##*busybox}" ] && o='ash -c' #cause its weird
set -- "$sh" $o "'$(cat <&3)'" -- "$@" #$@ = invoke $shell
time env - "$sh" $o "while echo; do echo; done|$*" #time (env - sh|sh) AC/DC
) 3<<-\SCRIPT
#Everything from here down is run by the different shells
i="${2:-1}" l="${1:-100}" d="${3:-
}"; set -- "\$((n=\$n\${n:++\$i}))\$d" #prep loop; prep eval
set -- $1$1$1$1$1$1$1$1$1$1 #yup
while read m #iterate on input
do [ $(($i*50+${n:=-$i})) -gt "$(($l-$i))" ] || #eval ok?
eval echo -n \""$1$1$1$1$1"\" #yay!
[ $((n=$i+$n)) -gt "$(($l-$i))" ] && #end game?
echo "$n" && exit #and EXIT
echo -n "$n$d" #damn - maybe next time
done #done
#END
SCRIPT #end heredoc
Ele incrementa uma variável uma vez por leitura de nova linha ou, como uma pequena otimização, se puder, incrementa 50 vezes por leitura de nova linha. Toda vez que a variável é incrementada, ela é impressa em stdout
. Ele se comporta muito como uma espécie de seq
cross nl
.
E só para deixar bem claro o que ele faz - aqui está uma saída set -x;
truncada depois de inseri-la antes de time
na função acima:
time env - /usr/bin/busybox ash -c '
while echo; do echo; done |
/usr/bin/busybox ash -c '"'$(
cat <&3
)'"' -- 20 5 busybox'
Assim, cada shell é chamado pela primeira vez como:
env - $shell -c "while echo; do echo; done |..."
... para gerar a entrada que precisará fazer um loop quando ler em 3<<\SCRIPT
- ou quando cat
, de qualquer forma. E no outro lado desse |pipe
ele se chama novamente como:
"...| $shell -c '$(cat <<\SCRIPT)' -- $args"
Então, além da chamada inicial para env
(porque cat
é realmente chamado na linha anterior) ; nenhum outro processo é chamado a partir do momento em que é chamado até sair. Pelo menos, espero que seja verdade.
Antes dos números ...
Eu deveria fazer algumas anotações sobre portabilidade.
-
posh
não gosta de$((n=n+1))
e insiste em$((n=$n+1))
-
mksh
não possuiprintf
embutido na maioria dos casos. Testes anteriores estavam muito atrasados - invocava/usr/bin/printf
para cada corrida. Daí oecho -n
acima. -
talvez mais do que eu me lembro ...
De qualquer forma, para os números:
for sh in dash busybox posh ksh mksh zsh bash
do sh_bench $sh 20 5 $sh 2>/dev/null
sh_bench $sh 500000 | wc -l
echo ; done
Isso vai levá-los todos de uma só vez ...
0dash5dash10dash15dash20
real 0m0.909s
user 0m0.897s
sys 0m0.070s
500001
0busybox5busybox10busybox15busybox20
real 0m1.809s
user 0m1.787s
sys 0m0.107s
500001
0posh5posh10posh15posh20
real 0m2.010s
user 0m2.060s
sys 0m0.067s
500001
0ksh5ksh10ksh15ksh20
real 0m2.019s
user 0m1.970s
sys 0m0.047s
500001
0mksh5mksh10mksh15mksh20
real 0m2.287s
user 0m2.340s
sys 0m0.073s
500001
0zsh5zsh10zsh15zsh20
real 0m2.648s
user 0m2.223s
sys 0m0.423s
500001
0bash5bash10bash15bash20
real 0m3.966s
user 0m3.907s
sys 0m0.213s
500001
ARBITRARY = TALVEZ OK?
Ainda assim, esse é um teste bastante arbitrário, mas testa entrada de leitura, avaliação aritmética e expansão de variáveis. Talvez não seja abrangente, mas possivelmente perto de lá.
EDITAR por Teresa e Junior : @mikeserv e eu fiz muitos outros testes (veja nosso chat para detalhes), e descobrimos que os resultados podem ser resumidos assim:
- Se você precisa de velocidade, vá definitivamente com o traço , é muito mais rápido do que qualquer outro shell e cerca de 4x mais rápido que o bash .
- Embora o shell do busybox possa ser muito mais lento que traço , em alguns testes ele pode ser mais rápido, porque possui muitos de seus próprios utilitários, como
grep
,sed
,sort
, etc., que não possuem tantos recursos quanto os utilitários GNU mais utilizados, mas podem realizar o trabalho tanto quanto. - Se a velocidade não é tudo o que você gosta, o ksh (ou ksh93 ) pode ser considerado o melhor compromisso entre velocidade e recursos. Sua velocidade se compara à menor mksh , que é muito mais rápida que bash , e também tem alguns recursos exclusivos, como aritmética de ponto flutuante .
- Embora o bash seja famoso por sua simplicidade, estabilidade e funcionalidade, foi o mais lento de todos os shells na maioria dos nossos testes e por uma grande margem.