GNU/Linux >> Tutoriales Linux >  >> Linux

¿Cuál es la forma más rápida de ejecutar un script?

Los terminales en estos días son más lentos de lo que solían ser, principalmente porque las tarjetas gráficas ya no se preocupan por la aceleración 2D. De hecho, imprimir en una terminal puede ralentizar un script, especialmente cuando se trata de desplazamiento.

En consecuencia ./script.sh es más lento que ./script.sh >script.log , que a su vez es más lento que /script.sh >/dev/null , porque estos últimos implican menos trabajo. Sin embargo, si esto hace una diferencia suficiente para cualquier propósito práctico depende de la cantidad de salida que produzca su secuencia de comandos y de la rapidez. Si su secuencia de comandos escribe 3 líneas y sale, o si imprime 3 páginas cada pocas horas, probablemente no necesite molestarse con las redirecciones.

Editar: Algunos puntos de referencia rápidos (y completamente rotos):

  • En una consola Linux, 240x75:

    $ time (for i in {1..100000}; do echo $i 01234567890123456789012345678901234567890123456789; done)
    real    3m52.053s
    user    0m0.617s
    sys     3m51.442s
    
  • En un xterm , 260x78:

    $ time (for i in {1..100000}; do echo $i 01234567890123456789012345678901234567890123456789; done)
    real    0m1.367s
    user    0m0.507s
    sys     0m0.104s
    
  • Redirigir a un archivo, en un disco Samsung SSD 850 PRO de 512 GB:

     $ time (for i in {1..100000}; do echo $i 01234567890123456789012345678901234567890123456789; done >file)
     real    0m0.532s
     user    0m0.464s
     sys     0m0.068s
    
  • Redirigir a /dev/null :

     $ time (for i in {1..100000}; do echo $i 01234567890123456789012345678901234567890123456789; done >/dev/null)
     real    0m0.448s
     user    0m0.432s
     sys     0m0.016s
    

Instintivamente habría estado de acuerdo con la respuesta de Satō Katsura; que tiene sentido. Sin embargo, es bastante fácil de probar.

Probé escribiendo un millón de líneas en la pantalla, escribiendo (añadiendo) a un archivo y redirigiendo a /dev/null . Probé cada uno de estos a su vez, luego hice cinco repeticiones. Estos son los comandos que usé.

$ time (for i in {1..1000000}; do echo foo; done)
$ time (for i in {1..1000000}; do echo foo; done > /tmp/file.log) 
$ time (for i in {1..1000000}; do echo foo; done > /dev/null)

Luego tracé los tiempos totales a continuación.

Como puede ver, las suposiciones de Satō Katsura eran correctas. Según la respuesta de Satō Katsura, también dudo que el factor limitante sea el resultado, por lo que es poco probable que la elección del resultado tenga un efecto sustancial en la velocidad general del guión.

FWIW, mi respuesta original tenía un código diferente, que tenía el archivo adjunto y /dev/null redirigir dentro el bucle.

$ rm /tmp/file.log; touch /tmp/file.log; time (for i in {1..1000000}; do echo foo >> /tmp/file.log; done) 
$ time (for i in {1..1000000}; do echo foo > /dev/null; done)

Como señala John Kugelman en los comentarios, esto agrega muchos gastos generales. Tal como está la pregunta, esta no es realmente la forma correcta de probarlo, pero lo dejaré aquí, ya que muestra claramente el costo de volver a abrir un archivo repetidamente desde dentro el guión en sí.

En este caso, los resultados se invierten.


Otra forma de acelerar un script es usar un intérprete de shell más rápido. Compara las velocidades de un POSIX bucle ocupado, ejecutar bajo bash v4.4 , ksh v93u+20120801 y dash v0.5.8 .

  1. bash :

    time echo 'n=0;while [ $n -lt 1000000 ] ; do \
                      echo $((n*n*n*n*n*n*n)) ; n=$((n+1)); 
                   done' | bash -s > /dev/null
    

    Salida:

    real    0m25.146s
    user    0m24.814s
    sys 0m0.272s
    
  2. ksh :

    time echo 'n=0;while [ $n -lt 1000000 ] ; do \
                      echo $((n*n*n*n*n*n*n)) ; n=$((n+1)); 
                   done' | ksh -s > /dev/null
    

    Salida:

    real    0m11.767s
    user    0m11.615s
    sys 0m0.010s
    
  3. dash :

    time echo 'n=0;while [ $n -lt 1000000 ] ; do \
                      echo $((n*n*n*n*n*n*n)) ; n=$((n+1)); 
                   done' | dash -s > /dev/null
    

    Salida:

    real    0m4.886s
    user    0m4.690s
    sys 0m0.184s
    

Un subconjunto de comandos en bash y ksh son compatibles con versiones anteriores de todos los comandos en dash . Un bash el script que solo usa comandos en ese subconjunto debería funcionar con dash .

Algunos bash los scripts que utilizan nuevas funciones se pueden convertir a otro intérprete. Si el bash script se basa en gran medida en las funciones más nuevas, puede que no valga la pena la molestia -- algunas nuevo bash las características son mejoras que son más fáciles de codificar y más eficiente, (a pesar de bash siendo generalmente más lento), por lo que el dash equivalente, (que podría implicar la ejecución de varios otros comandos), sería más lento.

En caso de duda, haz una prueba...


Linux
  1. ¿La forma "adecuada" de probar si un servicio se está ejecutando en un script?

  2. ¿Qué hace Echo $? ¿¿Hacer??

  3. ¿Cuál es la mejor manera de garantizar que solo se ejecute una instancia de un script Bash?

  4. ¿Cuál es la forma correcta de insertar una pestaña en sed?

  5. ¿Cuál es el uso de $# en Bash?

Manera de hacer que un script de Shell siempre se ejecute como raíz?

¿Para qué sirve el Colon Builtin ':' Sirve?

¿Cuál es la forma correcta de usar inotify?

¿Cuál es la forma más rápida de combinar dos o más archivos en Linux?

¿Cuál es la forma más rápida de mover un millón de imágenes de un directorio a otro en Linux?

¿Cuál es la mejor manera de verificar si un volumen está montado en un script Bash?