Mi shell de bash tarda entre 3 y 4 segundos en iniciarse, mientras que si lo inicio --norc
se ejecuta de inmediato.
Comencé a "perfilar" /etc/bash.bashrc
e ~/.bashrc
insertando manualmente return
declaraciones 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--norc
y--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\011
es un carácter de tabulación octal.Debería obtener un registro de seguimiento
/tmp/bashstart.PID.log
que 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 -x
más tarde y másset +x
temprano (o poner entre paréntesis varias secciones de interés selectivamente).Aunque no es tan fino como
date
los 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_XTRACEFD
para 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.txt
vastdout
ystdout
que se envíe normalmente (o se redirija por separado).fuente
exec
debería devolver fd2 a la normalidad, por lo que debería recuperar el mensaje.\D{...}
enPS4
permite que las cadenas de formato de tiempo completamente arbitrarias se expandan sin la sobrecarga de rendimiento del lanzamientodate
como un subproceso.date
entiende%N
y 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 -x
está en vigencia).Perfilado intento (4 respuestas)
Editar: marzo de 2016 agregar
script
mé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
,scriptreplay
y el archivo de tiempo .Finalmente, una pequeña comparación de actuaciones al final.
Uso
set -x
ydate
pero con horquillas limitadasTome la idea de @ DennisWilliamson, pero con la siguiente sintaxis, solo habrá una bifurcación inicial para 3 comandos:
Hacer esto
date
solo 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.log
y/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 debug
y/proc/timer_list
en kernels recientes de GNU / Linux, sin forks .Bajo los núcleos recientes de GNU / Linux , puede encontrar un
/proc
archivo 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
trap2
lugar detrap
como argumento para el comando de origen:Representará dos columnas como último comando y total :
Utilizando
strace
Sí,
strace
podrí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
,scriptreplay
y 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.log
contiene todos los rastros yscript.tim
es 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.bash
funciónpor
set -x
yPS4
por
set -x
y tenedor inicial a largo comando execpor
script
(yset +x
)Veces
Y compare los tiempos de ejecución (en mi host):
Salidas
por
elap.bash
funciónpor
set -x
yPS4
by
set -x
y fork inicial al comando exec largo (y mi segundopaste
script de muestra)por
strace
por
script
Conclusió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.
strace
Es una forma interesante, más detallada, pero difícil de leer.script
, conscriptreplay
y 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 momentostrace
y / oscript
tambié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.sh
y 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.sh
qué 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
trap
comando 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 -x
yset+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
Valgrind
perfilará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.d
en GH basado en el original ):puede rastrear el flujo de la función, incluidos los tiempos delta.
Salida de muestra:
Luego, utilizando el
sort -nrk7
comando, 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