Siempre pensé que el único beneficio de usar el guión en lugar de bash era que el guión era más pequeño y, por lo tanto, muchas instancias del guión comenzarían más rápido en el momento del arranque.
Pero he investigado un poco, y encontré que algunas personas migraron todos sus scripts para correr con la esperanza de que corrieran más rápido, y también encontré esto en el artículo DashAsBinSh en el Wiki de Ubuntu:
La razón principal para cambiar el shell predeterminado fue la eficiencia . bash es un excelente shell con todas las funciones apropiado para uso interactivo; de hecho, sigue siendo el shell de inicio de sesión predeterminado. Sin embargo, es bastante grande y lento para iniciar y operar en comparación con el tablero.
Hoy en día he estado usando muchos scripts de bash para muchas cosas en mi sistema, y mi problema es que tengo un script en particular que estoy ejecutando continuamente 24/7, que genera alrededor de 200 niños, que en conjunto calientan mi computadora 10 ° C más que en uso normal.
Es un script bastante grande con muchos bashismos, por lo que portarlos a POSIX u otro shell sería muy lento (y POSIX realmente no importa para uso personal), pero valdría la pena si pudiera reducir algo de esto Uso de CPU. Sé que también hay otras cosas a considerar, como llamar a un binario externo como sed
para un simple bashismo ${foo/bar}
, o en grep
lugar de =~
.
TL; DR es realmente más lento para iniciar y operar en comparación con el tablero. ¿Hay otros shells de Unix que son más eficientes que bash?
fuente
[
también debe ser un incorporado.bash
solía ser muy lento Avanzó mucho recientemente, pero para la mayoría de las cosas, todavía es más lento que la mayoría de los otros proyectiles.[ "$foo" != "${foo#*bar}" ]
maneja tu cosa grep. Y lased
cosa:while [ "$foo" != "${foo#*bar}" ]; do s=$s${foo%%bar*} foo=${foo#*bar} ; done ; foo=$s$foo
. Puedes poner cualquier cosa en una función.Respuestas:
SHELL SEQ:
Probablemente, un medio útil para evaluar el rendimiento de un proyectil es realizar muchas evaluaciones simples y muy pequeñas de forma repetitiva. Creo que es importante no solo hacer un bucle, sino hacer un bucle sobre la entrada , porque un shell necesita leer
<&0
.Pensé que esto complementaría las pruebas que @cuonglm ya publicó porque demuestra el rendimiento de un solo proceso de shell una vez invocado, a diferencia del suyo, lo que demuestra la rapidez con la que se carga un proceso de shell cuando se invoca. De esta manera, entre nosotros, cubrimos ambas caras de la moneda.
Aquí hay una función para facilitar la demostración:
Incrementa una variable una vez por lectura de nueva línea o, como una ligera optimización, si puede, aumenta 50 veces por lectura de nueva línea. Cada vez que se incrementa la variable se imprime en
stdout
. Se comporta mucho como una especie deseq
cruznl
.Y solo para dejar muy claro lo que hace: aquí hay un
set -x;
resultado truncado después de insertarlo justo antestime
en la función anterior:Entonces cada shell se llama primero como:
... para generar la entrada que necesitará recorrer cuando se lea
3<<\SCRIPT
, o cuando locat
haga, de todos modos. Y, por otro lado, se|pipe
vuelve a llamar a sí mismo como:Entonces, aparte de la llamada inicial a
env
(porque encat
realidad se llama en la línea anterior) ; no se invocan otros procesos desde el momento en que se llama hasta que sale. Al menos, espero que sea cierto.Antes de los números ...
Debo tomar algunas notas sobre la portabilidad.
posh
no le gusta$((n=n+1))
e insiste en$((n=$n+1))
mksh
no tiene unprintf
incorporado en la mayoría de los casos. Las pruebas anteriores lo retrasaron mucho: invocaba/usr/bin/printf
para cada carrera. De ahí loecho -n
anterior.tal vez más como lo recuerdo ...
De todos modos, a los números:
Eso los conseguirá de una vez ...
ARBITRARIO = QUIZÁS OK?
Aún así, esta es una prueba bastante arbitraria, pero prueba la entrada de lectura, la evaluación aritmética y la expansión variable. Quizás no comprensivo, pero posiblemente cerca de allí
EDITAR por Teresa e Junior : @mikeserv y yo hemos realizado muchas otras pruebas (vea nuestro chat para más detalles), y encontramos que los resultados podrían resumirse así:
grep
,sed
,sort
, etc., que no tienen tantas características como el uso general de GNU utilidades, pero puede hacer el trabajo tanto.fuente
4.2.37(1)-release
desde Debian y4.2.45(2)-release
desde un Porteus LiveCD (Slackware). Sinnull=
, en lugar de generar números, funciona como si presionase Intro continuamente, luego tengo que matar a bash con SIGKILL .bash --posix
, sin éxito.zsh
.zsh
secuestrarátty
y bueno, lanzará un shell interactivo. Espero quebash
haga lo mismo, por lo que tengo cuidado de solo llamar a su--posix
enlace. Puedo hacer que haga lo que espera para la mayoría de ellos, pero puede ser más trabajo de lo que vale. ¿Estás llamandobash
o estás llamandosh
?Deja hacer un punto de referencia.
Con
bash
:Con
dash
:Cada iteración solo inicia un shell y no hace nada con el operador sin operación: dos puntos , luego se cierra.
Como muestra el resultado,
dash
es extremadamente más rápido quebash
al inicio.dash
es más pequeño y depende de una biblioteca menos compartida quebash
:Esto se trata del tiempo de inicio, ¿qué hay de operar? Dejemos hacer otro punto de referencia:
Con prueba simple
1 = 1
,dash
aún mucho más rápido quebash
.fuente
seq 1 100000
debería serseq 1 1000
?dash
caso de prueba es soloseq 1 1000
?1000
para iniciar y1000000
operar, arreglado.Aquí hay algunos tiempos de inicio de varios shells en UNIX certificado (Mac OS X 10.10.3). Reescribí la prueba para usar tcsh para controlar los bucles de modo que el shell que se estaba probando no fuera el que controlaba los bucles. Para cada shell, el bucle se ejecuta cinco veces antes de la temporización, para garantizar que el ejecutable del shell y los scripts estén en caché.
Como puede ver, no hay un ganador claro, pero hay un perdedor definitivo. De todos modos, bash 4 es claramente más lento que bash 3. Dash funciona bien, pero dado que ksh93 ahora es de código abierto, no hay una razón real para no usarlo para todo (disculpas si no entiendo las bondades de licencia): ksh93 es rápido, sólido , y un estándar de facto en UNIX-land (si no en GNU / Linux-land); proporciona un superconjunto de la funcionalidad del shell POSIX (por lo que yo entiendo, el shell POSIX se basó en ksh88); es igual a bash como un shell interactivo, aunque rezagado en comparación con tcsh. Y el perdedor es, por supuesto, zsh.
fuente
Hay demasiados casos de prueba injustos en muchas respuestas aquí. Si prueba dos shells, use la sintaxis correcta para cada una de ellas. Y en bash, los doble paréntesis son mucho más rápidos y confiables que los simples, por lo que hay una diferencia de velocidad mucho menor. También use bashisms optimizados y luego estas diferencias de velocidad son más pequeñas también. En mi sistema, bash funciona como el infierno, con un fuerte uso de bashismos. Y los equivalentes posix en el guión son más lentos aquí. Esto no es correcto porque el guión siempre es varias veces más rápido que bash. Realmente es bastante injusto comparar las líneas de comando posix en ambos, que dash siempre puede ser el más rápido. En mi opinión, posix está muy desactualizado. Y en términos de compatibilidad, es realmente difícil encontrar sistemas relevantes hoy en día, no utilizaron un shell bash.
Una buena comparación es: usar la mejor línea de comando posible en cada shell, para finalizar un trabajo específico. No solo exactamente la misma línea de comando, cuando solo un shell realmente tiene una ventaja aquí. Las comparaciones como esta no son confiables y no muestran el rendimiento real de los competidores. Veo en mi trabajo diario, qué shell es más rápido en muchos casos de uso.
Por ejemplo, para reemplazar todos los
a
caracteres en la cadena conb
caracteres, en bash se puede escribir"${varname//a/b}"
, mientras que en el tablero que tiene que llamar a la herramienta externa como esto:"$(echo "$varname" | sed 's/a/b/g')"
. Si tiene que repetirlo cientos de veces, usar el bashism puede darle una aceleración 2x.fuente