Meu shell bash leva de 3 a 4 segundos para iniciar, enquanto se eu iniciá-lo, --norc
ele é executado imediatamente.
Comecei a "criar perfis" /etc/bash.bashrc
e ~/.bashrc
inserindo return
instruções manualmente e buscando melhorias na velocidade, mas não é um processo quantitativo e não é eficiente.
Como posso criar um perfil dos meus scripts bash e ver quais comandos levam mais tempo para iniciar?
time bash -c 'exit'
etime bash -i -c 'exit'
e pode jogar com--norc
e--noprofile
.Respostas:
Se você possui o GNU
date
(ou outra versão que pode gerar nanossegundos), faça isso no início de/etc/bash.bashrc
(ou onde você desejar iniciar um rastreamento em qualquer script do Bash):adicionar
no final de
~/.bashrc
(ou no final da seção de qualquer script do Bash que você deseja rastrear para parar). O\011
é um caractere de tabulação octal.Você deve obter um log de rastreamento
/tmp/bashstart.PID.log
que mostre o carimbo de data e hora de segundos. Nanossegundos de cada comando que foi executado. A diferença de uma vez para a outra é a quantidade de tempo que a etapa intermediária levou.À medida que reduz as coisas, você pode se mover
set -x
mais tarde e maisset +x
cedo (ou agrupar várias seções de interesse seletivamente).Embora não seja tão refinado quanto
date
os nanossegundos do GNU , o Bash 5 inclui uma variável que fornece o tempo em microssegundos. Seu uso evita que você crie um executável externo para todas as linhas e funcione em Macs ou em outro lugar que não possua GNUdate
- desde que você tenha o Bash 5, é claro. Altere a configuração dePS4
:Conforme apontado por @pawamoy, você pode
BASH_XTRACEFD
enviar a saída do rastreio para um descritor de arquivo separado, se você tiver o Bash 4.1 ou posterior. A partir desta resposta :Isso fará com que a saída de rastreio vá para o arquivo
command.txt
saindostdout
e saiastdout
normalmente (ou seja redirecionada separadamente).fonte
exec
deve retornar o fd2 ao normal, para que você retorne o prompt.\D{...}
inPS4
permite que sequências de formato de tempo completamente arbitrárias sejam expandidas sem a sobrecarga de desempenho do lançamentodate
como um subprocesso.date
entende%N
e o Bash 4.2 não (porquestrftime(3)
não) no sistema GNU - tão arbitrário com limites. Sua opinião sobre desempenho versus resolução é boa e o usuário deve fazer a escolha com sabedoria, lembrando que o impacto no desempenho é temporário apenas durante a depuração (e somente quandoset -x
está em vigor).Criação de perfil festança (4 respostas)
Editar: março de 2016 adicionar
script
métodoLendo isso e porque a criação de perfil é uma etapa importante, fiz alguns testes e pesquisas sobre toda essa questão do SO e já postei respostas.
Há 4+ respostas:
A última utilização
script
,scriptreplay
e arquivo tempo .Finalmente, uma pequena comparação de performances no final.
Usando
set -x
edate
com garfos limitadosRespeite a ideia de @ DennisWilliamson, mas com a seguinte sintaxe, haverá apenas uma bifurcação inicial para 3 comandos:
Fazer isso será executado
date
apenas uma vez. Há uma demonstração / teste rápido para mostrar como funciona:Exemplo de script:
Ao executar esse script, você cria 2 arquivos:
/tmp/sample-XXXX.log
e/tmp/sample-XXXX.tim
(onde XXXX é a identificação do processo de execução do script).Você pode apresentá-los usando
paste
:Ou você pode até calcular o tempo de diferença:
ou em duas colunas:
Pode render:
Usando
trap debug
e/proc/timer_list
nos kernels recentes do GNU / Linux, sem forks .Nos kernels recentes do GNU / Linux , você pode encontrar um
/proc
arquivo chamadotimer_list
:Onde o tempo atual é a soma de
5461935212966259 + 1383718821564493249
, mas em nanossegundos.Portanto, para calcular o tempo decorrido , não há necessidade de saber o deslocamento.
Para esse tipo de trabalho, escrevi elap.bash (V2) , que é originado pela seguinte sintaxe:
ou
(Veja os comentários para obter a sintaxe completa)
Então você pode simplesmente adicionar esta linha na parte superior do seu script:
Pouca amostra:
Renderize no meu host:
Usando em
trap2
vez detrap
como argumento para o comando source:Renderizará o último comando e o total de duas colunas :
Usando
strace
Sim,
strace
poderia fazer o trabalho:Mas poderia fazer muitas coisas!
Usando um comando mais restrito:
Despejará um log mais leve:
Dependendo do que você está procurando, você pode ser mais restritivo:
Lê-los será um pouco mais difícil:
O script bash original não é tão fácil de seguir neste ...
Usando
script
,scriptreplay
e cronometrando arquivoComo parte do BSD Utils ,
script
(escriptreplay
) é uma ferramenta muito antiga que pode ser usada para fazer o perfil do bash, com uma área muito pequena.Vai produzir:
e gere dois arquivos:
O arquivo
script.log
contém todos os rastreios escript.tim
é o arquivo de temporização :Você pode ver a execução do tempo total com a primeira e a última linha do arquivo de log e / ou resumindo os tempos no arquivo de temporização:
No arquivo de temporização, o segundo valor é o número de próximos bytes no arquivo de log correspondente. Isso permite reproduzir o arquivo de log opcionalmente com um fator de aceleração :
ou
ou
Mostrar horários e comandos lado a lado também é um pouco mais complexo:
Testes e conclusão
Para fazer testes, baixei o segundo exemplo no bash complex hello world , esse script leva aproximadamente 0,72 s para ser concluído no meu host.
Eu adicionei no topo do script um dos seguintes:
por
elap.bash
funçãopor
set -x
ePS4
por
set -x
e bifurcação inicial ao comando exec longopor
script
(eset +x
)Vezes
E compare os tempos de execução (no meu host):
Saídas
por
elap.bash
funçãopor
set -x
ePS4
by
set -x
e fork inicial para o comando exec longo (e meu segundopaste
script de exemplo)de
strace
de
script
Conclusão
Bem! Se meu bash puro for mais rápido do que bifurcar até o momento em cada comando , meu bash puro implica algumas operações em cada comando.
A maneira de dedicar um processo independente para registro e armazenamento é claramente mais eficiente.
strace
é uma maneira interessante, mais detalhada, mas difícil de ler.script
, withscriptreplay
e fator de aceleração também é muito bom, não é a mesma precisão, pois ela é baseada na troca de console em vez da execução do processo, mas muito leve e eficiente (sem o mesmo objetivo, sem o mesmo uso).Por fim, acho que quanto mais eficiente, em legibilidade e desempenho
set + 1 fork
, é o primeiro desta resposta, mas, dependendo do caso específico, uso em algum momentostrace
e / ouscript
também.fonte
exec {BASH_XTRACEFD}>
em vez deexec 3>&2 2>
que irá preencher o arquivo de log somente com a saída de registro de rastreamento e não outra saída stderr.script.sh
, eu posso fazerbash -c "exec {BASH_XTRACEFD}> >(tee trace.log | sed -u 's/^.*$//' | date -f - +%s.%N > timing.log); set -x; . script.sh
e obter dados de criação de perfil sem modificarscript.sh
. Quando a precisão de sub-segundo não é necessária, eu gosto debash -c "exec {BASH_XTRACEFD}>trace.log; set -x; PS4='+\t'; . script.sh
qual horário registra cada linha de rastreamento com segunda precisão e sem bifurcar até a data (sobrecarga baixa).Muitas vezes, ajuda a rastrear as chamadas do sistema
Do manual:
-c Conte o tempo, as chamadas e os erros de cada chamada do sistema e relate um resumo da saída do programa.
-f Rastrear processos filho ...
Não é exatamente isso que você deseja e o que um criador de perfil orientado a linhas mostraria para você, mas geralmente ajuda a encontrar pontos de acesso.
fonte
Você pode dar uma olhada no
trap
comando com a condição DEBUG . Existe uma maneira de definir um comando a ser executado junto com seus comandos. Veja as notas na resposta.fonte
help trap
: "Se um SIGNAL_SPEC for DEBUG, o ARG será executado antes de cada comando simples." No Bash 3.2, diz "depois". Isso é um erro de digitação. A partir do Bash 2.05b, ele era executado antes. Referência : "Este documento detalha as alterações entre esta versão, bash-2.05b-alpha1, e a versão anterior, bash-2.05a-release. ... 3. Novos recursos no Bash ... w. A interceptação DEBUG está agora execute antes de comandos simples, ((...)) comandos, [...] comandos condicionais e para ((...)) loops. " O teste em cada versão confirma que é anterior .Tempo, xtrace, bash -x
set -x
eset+x
( http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_02_03.html ) continuam sendo a maneira ortodoxa de depurar um script.Não obstante, para ampliar nosso horizonte, é possível verificar alguns sistemas para depuração e criação de perfil disponíveis para os programas Linux comuns [aqui uma das listas] , por exemplo, deve resultar útil em um baseado em valgrind, especialmente para depurar memória ou sysprof para criar um perfil todo o sistema:
Para sysprof:
E depois selecione o ramo de subprocessos que você achar interessante.
Para o Valgrind:
Com um pouco mais de academia, parece possível tornar visível para o Valgrind alguns programas que geralmente instalamos a partir do binário (por exemplo, OpenOffice ).
É possível ler as perguntas frequentes do valgrind que analisarão
Valgrind
os processos filhos, se solicitado explicitamente.Isso será feito com esta opção ativada
Referências adicionais:
fonte
Esta postagem de Alan Hargreaves descreve o método de criação de perfil de script de shell Bourne usando o provedor DTrace. Tanto quanto sei, isso funciona com o Solaris e o OpenSolaris (consulte: / bin / sh DTrace Provider ).
Dado o seguinte script dtrace (
sh_flowtime.d
no GH com base no original ):você pode rastrear o fluxo da função, incluindo tempos delta.
Saída de amostra:
Em seguida, usando o
sort -nrk7
comando, você pode classificar a saída para mostrar as chamadas que mais consomem.Não conheço nenhum fornecedor de probes disponível para outros shells, assim como algumas pesquisas (pesquisa no GitHub?) Ou, se você quiser investir algum tempo, pode escrevê-lo com base no exemplo sh existente : (consulte: Como ativar sh Provedor DTrace? ).
fonte