Eu sempre pensei que o único benefício do uso do traço em vez do bash era que o traço era menor e, portanto, muitas instâncias do traço começariam mais rapidamente no momento da inicialização.
Mas eu fiz algumas pesquisas e encontrei algumas pessoas migrando todos os seus scripts para correr na esperança de que rodassem mais rapidamente, e também encontrei isso no artigo DashAsBinSh no Ubuntu Wiki:
O principal motivo para mudar o shell padrão foi a eficiência . o bash é um excelente shell completo adequado para uso interativo; de fato, ainda é o shell de login padrão. No entanto, é bastante grande e lento iniciar e operar em comparação com o traço.
Atualmente, eu tenho usado muitos scripts bash para muitas coisas no meu sistema, e meu problema é que eu tenho um script específico que estou executando continuamente 24/7, que gera cerca de 200 crianças, que juntas aquecem meu computador 10 ° C mais do que no uso normal.
É um script bastante grande, com muitos basismos, portanto, portá-los para o POSIX ou algum outro shell consumiria muito tempo (e o POSIX realmente não importa para uso pessoal), mas valeria a pena se eu pudesse reduzir um pouco disso. Utilização do CPU. Eu sei que também há outras coisas a considerar, como chamar um binário externo como sed
um simples basismo ${foo/bar}
, ou em grep
vez de =~
.
TL; DR é realmente mais lento para iniciar e operar em comparação com o traço? Existem outros shells Unix que são mais eficientes que o bash?
fonte
[
também deve ser incorporado.bash
costumava ser muito lento. Ele fez muito progresso recentemente, mas para a maioria das coisas, ainda é mais lento que a maioria das outras conchas.[ "$foo" != "${foo#*bar}" ]
lida com sua coisa grep. E ased
coisa:while [ "$foo" != "${foo#*bar}" ]; do s=$s${foo%%bar*} foo=${foo#*bar} ; done ; foo=$s$foo
. Você pode colocar qualquer coisa em uma função.Respostas:
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:
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 deseq
cruznl
.E apenas para deixar bem claro o que faz - aqui está uma
set -x;
saída truncada depois de inseri-la antestime
na função acima:Portanto, cada shell é chamado primeiro como:
... para gerar a entrada que ele precisará fazer loop quando ler
3<<\SCRIPT
- ou quandocat
, de qualquer maneira. E por outro lado,|pipe
ele se chama novamente como:Portanto, além da chamada inicial para
env
(porquecat
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 umprintf
builtin na maioria dos casos. Testes anteriores estavam muito atrasados - eram invocadores/usr/bin/printf
a cada execução. Daí oecho -n
acima.talvez mais do que me lembro ...
Enfim, para os números:
Isso vai levá-los de uma só vez ...
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:
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.fonte
4.2.37(1)-release
no Debian e4.2.45(2)-release
no Porteus LiveCD (Slackware). Semnull=
, em vez de emitir números, ele funciona como se eu tivesse pressionado Return continuamente, então eu tenho que matar o bash com SIGKILL .bash --posix
, sem sucesso.zsh
.zsh
seqüestrará oetty
bem, ele lançará um shell interativo. Esperobash
que faça o mesmo - e é por isso que tenho o cuidado de chamar apenas seu--posix
link. Posso fazer o que você espera da maioria deles, mas pode ser mais trabalhoso do que vale a pena. Você está ligandobash
ou está ligandosh
?Vamos fazer uma referência.
Com
bash
:Com
dash
:Cada iteração inicia apenas um shell e não faz nada com o operador não operacional - dois pontos e , em seguida, sai.
Como mostra o resultado,
dash
é extremamente mais rápido do quebash
na inicialização.dash
é menor e depende de menos biblioteca compartilhada quebash
:É sobre o tempo de inicialização, que tal operar. Vamos fazer outra referência:
Com teste simples
1 = 1
,dash
ainda muito mais rápido quebash
.fonte
seq 1 100000
deveria serseq 1 1000
?dash
caso de teste é apenasseq 1 1000
?1000
para inicialização e1000000
operação, fixo.Aqui estão alguns horários de inicialização de vários shells em um UNIX certificado (Mac OS X 10.10.3). Reescrevi o teste para usar o tcsh para controlar os loops, para que o shell que estava sendo testado não fosse o responsável pelo controle dos loops. Para cada shell, o loop é executado cinco vezes antes do tempo, para garantir que o shell executável e os scripts estejam em cache.
Como você pode ver, não há vencedor nítido, mas há um perdedor definitivo. De qualquer forma, o bash 4 é nitidamente mais lento que o bash 3. O Dash tem um bom desempenho, mas, como o ksh93 agora é de código aberto, não há motivo real para não usá-lo para tudo (desculpas se eu não entender as sutilezas do licenciamento): o ksh93 é rápido, sólido , e um padrão de fato na terra UNIX (se não na terra GNU / Linux); fornece um superconjunto da funcionalidade do shell POSIX (até onde eu entendi, o shell POSIX foi baseado no ksh88); é igual ao bash como um shell interativo, embora atrasado em comparação com o tcsh. E o perdedor é obviamente zsh.
fonte
Existem muitos casos de teste injustos em muitas respostas aqui. Se testar duas conchas, use a sintaxe correta para cada uma delas. E no bash, os colchetes duplos são muito mais rápidos e confiáveis do que os colchetes simples, portanto, há uma diferença de velocidade muito menor. Use também bashisms otimizados e, em seguida, essas diferenças de velocidade também serão menores. No meu sistema, o bash funciona como o inferno, com uso pesado de bashisms. E os equivalentes posix no painel são mais lentos aqui. Não é correto que o traço seja sempre várias vezes mais rápido que o bash. Realmente, é bastante injusto comparar as linhas de comando do posix em ambos, que podem sempre ser os mais rápidos. Na minha opinião, o posix está muito desatualizado. E em termos de compatibilidade, é realmente difícil encontrar sistemas relevantes hoje em dia, eles não usavam um shell bash.
Uma boa comparação é: usar a melhor linha de comando possível em cada shell, para concluir um trabalho específico. Não apenas exatamente a mesma linha de comando, quando apenas um shell realmente tem uma vantagem aqui. Comparações como essa não são confiáveis e não mostraram o desempenho real dos concorrentes. Eu vejo no meu trabalho diário, qual shell é mais rápido em muitos casos de uso.
Por exemplo, para substituir todos os
a
caracteres na string comb
caracteres, em bash você pode escrever"${varname//a/b}"
enquanto na corrida você tem que chamar ferramenta externa como esta:"$(echo "$varname" | sed 's/a/b/g')"
. Se você precisar repeti-lo algumas centenas de vezes - usar o basismo pode dar 2x velocidade.fonte