Mi shell de bash tarda entre 3 y 4 segundos en iniciarse, mientras que si lo inicio --norcse ejecuta de inmediato.
Comencé a "perfilar" /etc/bash.bashrce ~/.bashrcinsertando manualmente returndeclaraciones y buscando mejoras de velocidad, pero no es un proceso cuantitativo y no es eficiente.
¿Cómo puedo perfilar mis scripts de bash y ver qué comandos tardan más en iniciarse?

time bash -c 'exit'ytime bash -i -c 'exit'y puedes jugar con--norcy--noprofile.Respuestas:
Si tiene GNU
date(u otra versión que puede generar nanosegundos), haga esto al comienzo de/etc/bash.bashrc(o donde quiera que comience un rastreo en cualquier script Bash):añadir
al final de
~/.bashrc(o al final de la sección de cualquier script de Bash que le gustaría detener el seguimiento). El\011es un carácter de tabulación octal.Debería obtener un registro de seguimiento
/tmp/bashstart.PID.logque muestre la marca de tiempo segundos.nanosegundos de cada comando que se ejecutó. La diferencia de una vez a la siguiente es la cantidad de tiempo que tomó el paso intermedio.A medida que reduce las cosas, puede moverse
set -xmás tarde y másset +xtemprano (o poner entre paréntesis varias secciones de interés selectivamente).Aunque no es tan fino como
datelos nanosegundos de GNU , Bash 5 incluye una variable que da el tiempo en microsegundos. Usarlo le evita generar un ejecutable externo para cada línea y funciona en Mac o en cualquier otro lugar que no tenga GNUdate, siempre que tenga Bash 5, por supuesto. Cambiar la configuración dePS4:Como señaló @pawamoy, puede usar
BASH_XTRACEFDpara enviar la salida de la traza a un descriptor de archivo separado si tiene Bash 4.1 o posterior. De esta respuesta :Esto hará que la salida de rastreo vaya al archivo que se
command.txtvastdoutystdoutque se envíe normalmente (o se redirija por separado).fuente
execdebería devolver fd2 a la normalidad, por lo que debería recuperar el mensaje.\D{...}enPS4permite que las cadenas de formato de tiempo completamente arbitrarias se expandan sin la sobrecarga de rendimiento del lanzamientodatecomo un subproceso.dateentiende%Ny Bash 4.2 no (porquestrftime(3)no) en el sistema GNU, tan arbitrario con límites. Su punto sobre el rendimiento versus la resolución es bueno y el usuario debe tomar una decisión sabia, teniendo en cuenta que el impacto en el rendimiento es temporal solo durante la depuración (y solo cuandoset -xestá en vigencia).Perfilado intento (4 respuestas)
Editar: marzo de 2016 agregar
scriptmétodoAl leer esto y porque la creación de perfiles es un paso importante, he realizado algunas pruebas e investigaciones sobre toda esta pregunta SO y ya he publicado respuestas.
Hay 4+ respuestas:
El último uso
script,scriptreplayy el archivo de tiempo .Finalmente, una pequeña comparación de actuaciones al final.
Uso
set -xydatepero con horquillas limitadasTome la idea de @ DennisWilliamson, pero con la siguiente sintaxis, solo habrá una bifurcación inicial para 3 comandos:
Hacer esto
datesolo se ejecutará una vez. Hay una demostración / prueba rápida para mostrar cómo funciona:Script de muestra:
Al ejecutar este script, crea 2 archivos:
/tmp/sample-XXXX.logy/tmp/sample-XXXX.tim(donde XXXX es la identificación del proceso del script en ejecución).Puede presentarlos usando
paste:O incluso puede calcular el tiempo de diferencia:
o en dos columnas:
Puede renderizar:
Utilizando
trap debugy/proc/timer_listen kernels recientes de GNU / Linux, sin forks .Bajo los núcleos recientes de GNU / Linux , puede encontrar un
/procarchivo llamadotimer_list:Donde el tiempo actual es la suma de
5461935212966259 + 1383718821564493249, pero en nanosegundos.Entonces, para calcular el tiempo transcurrido , no hay necesidad de conocer el desplazamiento.
Para este tipo de trabajos, escribí elap.bash (V2) , que se obtiene de la siguiente sintaxis:
o
(Ver comentarios para sintaxis completa)
Entonces, simplemente podría agregar esta línea en la parte superior de su script:
Pequeña muestra:
Hacer en mi host:
Usando en
trap2lugar detrapcomo argumento para el comando de origen:Representará dos columnas como último comando y total :
Utilizando
straceSí,
stracepodría hacer el trabajo:¡Pero podría hacer muchas cosas!
Usando un comando más restringido:
Volcará el registro más ligero:
Dependiendo de lo que esté buscando, puede ser más restrictivo:
Leerlos será un poco más difícil:
El guión original de bash no es tan fácil de seguir en este ...
Utilizando
script,scriptreplayy el archivo de sincronizaciónComo parte de BSD Utils ,
script(yscriptreplay) es una herramienta muy antigua que se puede usar para perfilar bash, con una huella muy pequeña.Producirá:
y generar dos archivos:
El archivo
script.logcontiene todos los rastros yscript.times el archivo de tiempo :Puede ver la ejecución del tiempo total con la primera y última línea del archivo de registro y / o resumiendo los tiempos en el archivo de tiempo:
En el archivo de temporización, el segundo valor es el número de bytes siguientes en el archivo de registro correspondiente. Esto le permite reproducir el archivo de registro opcionalmente con un factor de aceleración :
o
o
Mostrar tiempos y comandos uno al lado del otro también es un poco más complejo:
Pruebas y conclusión
Para realizar pruebas, descargué una segunda muestra en bash complex hello world , este script tarda aproximadamente 0,72 segundos en completarse en mi host.
He agregado en la parte superior del script uno de:
por
elap.bashfunciónpor
set -xyPS4por
set -xy tenedor inicial a largo comando execpor
script(yset +x)Veces
Y compare los tiempos de ejecución (en mi host):
Salidas
por
elap.bashfunciónpor
set -xyPS4by
set -xy fork inicial al comando exec largo (y mi segundopastescript de muestra)por
stracepor
scriptConclusión
¡Bien! Si mi bash puro es más rápido que bifurcar hasta la fecha en cada comando , mi bash puro implica algunas operaciones en cada comando.
La forma de dedicar un proceso independiente para el registro y el almacenamiento es claramente más eficiente.
straceEs una forma interesante, más detallada, pero difícil de leer.script, conscriptreplayy el factor de aceleración también es muy bueno, no es la misma precisión ya que se basa en el intercambio de la consola en lugar de la ejecución del proceso, pero es muy ligero y eficiente (no es el mismo objetivo, no es el mismo uso).Finalmente, creo que lo más eficiente, en cuanto a legibilidad y rendimiento es
set + 1 fork, La primera de esta respuesta, pero en fin, dependiendo del caso específico, lo uso en algún momentostracey / oscripttambién.fuente
exec {BASH_XTRACEFD}>lugar deexec 3>&2 2>lo que completará el archivo de registro solo con la salida del registro de seguimiento y no con otra salida stderr.script.sh, solo puedo hacerbash -c "exec {BASH_XTRACEFD}> >(tee trace.log | sed -u 's/^.*$//' | date -f - +%s.%N > timing.log); set -x; . script.shy obtener datos de perfil sin modificarscript.sh. Cuando no se necesita precisión por debajo del segundo, me gustabash -c "exec {BASH_XTRACEFD}>trace.log; set -x; PS4='+\t'; . script.shqué marca de tiempo marca cada línea de traza con una segunda precisión y sin bifurcación hasta la fecha (bajo costo).A menudo ayuda rastrear las llamadas del sistema
Del manual:
-c Cuente el tiempo, las llamadas y los errores para cada llamada al sistema e informe un resumen al salir del programa.
-f Rastrear procesos secundarios ...
Esto no es exactamente lo que desea y lo que le mostraría un generador de perfiles orientado a líneas, pero generalmente ayuda a encontrar puntos calientes.
fuente
Puede echar un vistazo al
trapcomando con la condición DEBUG . Hay una manera de configurar un comando (s) para que se ejecute junto con sus comandos. Ver las notas a la respuesta.fuente
help trap: "Si un SIGNAL_SPEC es DEBUG, ARG se ejecuta antes de cada comando simple". En Bash 3.2, dice "después". Eso es un error tipográfico. A partir de Bash 2.05b, se ejecuta antes. Referencia : "Este documento detalla los cambios entre esta versión, bash-2.05b-alpha1, y la versión anterior, bash-2.05a-release. ... 3. Nuevas características en Bash ... w. La trampa DEBUG ahora es ejecutar antes de comandos simples, ((...)) comandos, [[]] comandos condicionales y para ((...)) bucles ". Las pruebas en cada versión confirman que es antes .Time, xtrace, bash -x
set -xyset+x( http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_02_03.html ) siguen siendo la forma ortodoxa de depurar un script.Sin embargo, para ampliar nuestro horizonte, es posible realizar una verificación en algún sistema para la depuración y la creación de perfiles disponibles para los programas habituales de Linux [aquí una de las listas] , por ejemplo, debería resultar útil en función de valgrind, especialmente para depurar memoria o sysprof para perfilar todo el sistema:
Para sysprof:
Y después de seleccionar la rama de subprocesos que le parezca interesante.
Para Valgrind:
con un poco más de gimnasio, parece que es posible hacer visibles para Valgrind algunos programas que generalmente instalamos desde binarios (por ejemplo, OpenOffice ).
Es posible leer las preguntas frecuentes de valgrind que
Valgrindperfilarán los procesos secundarios si se solicita explícitamente.Lo hará con esta opción habilitada
Referencias adicionales
fuente
Esta publicación de Alan Hargreaves describe el método para perfilar el script de shell Bourne utilizando el proveedor DTrace. Hasta donde yo sé, esto funciona con Solaris y OpenSolaris (ver: / bin / sh DTrace Provider ).
Entonces, dado el siguiente script dtrace (
sh_flowtime.den GH basado en el original ):puede rastrear el flujo de la función, incluidos los tiempos delta.
Salida de muestra:
Luego, utilizando el
sort -nrk7comando, puede ordenar la salida para mostrar las llamadas más consumidoras.No conozco ningún proveedor de sondas disponibles para otros shells, así que investigue un poco (¿busca en GitHub?) O si desea invertir algo de tiempo, puede escribirlo según el ejemplo sh existente : (ver: Cómo activar sh Proveedor de DTrace? ).
fuente