SHELL SEQ:
Provavelmente, um meio útil de comparar o desempenho de um shell é fazer várias avaliações muito pequenas e simples repetidamente. Acho que é importante não apenas fazer um loop, mas fazer um loop sobre a entrada , porque um shell precisa ler <&0
.
Eu pensei que isso complementaria os testes que o @cuonglm já postou, porque demonstra o desempenho de um único processo de shell uma vez invocado, em oposição ao que demonstra a rapidez com que um processo de 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 leve otimização, se puder, incrementa 50 vezes por leitura de nova linha. Sempre que a variável é incrementada, ela é impressa stdout
. Ele se comporta muito como uma espécie de seq
cruz nl
.
E apenas para deixar bem claro o que faz - aqui está uma set -x;
saída truncada depois de inseri-la antes 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'
Portanto, cada shell é chamado primeiro como:
env - $shell -c "while echo; do echo; done |..."
... para gerar a entrada que ele precisará fazer loop quando ler 3<<\SCRIPT
- ou quando cat
, de qualquer maneira. E por outro lado, |pipe
ele se chama novamente como:
"...| $shell -c '$(cat <<\SCRIPT)' -- $args"
Portanto, além da chamada inicial para env
(porque cat
na verdade é chamada na linha anterior) ; nenhum outro processo é chamado desde o momento em que é chamado até sua saída. Pelo menos, espero que seja verdade.
Antes dos números ...
Eu deveria fazer algumas anotações sobre portabilidade.
posh
não gosta $((n=n+1))
e insiste em$((n=$n+1))
mksh
não tem um printf
builtin na maioria dos casos. Testes anteriores estavam muito atrasados - eram invocadores /usr/bin/printf
a cada execução. Daí o echo -n
acima.
talvez mais do que me lembro ...
Enfim, 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 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
ARBITRÁRIO = TALVEZ OK?
Ainda assim, este é 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á.
EDIT por Teresa e Junior : @mikeserv e eu fizemos muitos outros testes (veja nosso bate-papo para mais detalhes), e achamos que os resultados podem ser resumidos assim:
- Se você precisar de velocidade, vá definitivamente com o traço , é muito mais rápido que qualquer outro shell e cerca de 4x mais rápido que o bash .
- Enquanto busybox shell 's pode ser muito mais lento do que o traço , em alguns testes que poderia ser mais rápido, porque tem muitos de seus próprios utilitários userland, como
grep
, sed
, sort
, etc., que não tem tantos recursos como o GNU comumente usado utilitários, mas pode fazer o trabalho da mesma maneira.
- 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 ao mksh menor , que é muito mais rápido que o bash , e também possui alguns recursos exclusivos, como a 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.