Cronometrar seus scripts e procedimentos de bash de dentro do código

Cronometrar seus scripts e procedimentos de bash de dentro do código

Em geral, pode -se usar o tempo Utilitário Bash (ver Homem hora Para obter mais informações) para executar um programa e obter a duração do tempo de execução e resumos de uso de recursos do sistema. Mas como uma vez pode seções específicas de código, diretamente de dentro do código -fonte Bash?

Usando algumas atribuições e cálculos de variáveis ​​fáceis, é possível obter métricas de tempo precisa para execuções de scripts do Bash.

Neste tutorial, você aprenderá:

  • Como fazer scripts de bases usando atribuições e cálculos variáveis
  • Como usar temporizadores sobrepostos para seções específicas de tempo de seus scripts
  • Exemplos que exemplificam como seções específicas de código podem ser cronometradas
Execução de scripts do Bash Timing

Requisitos de software e convenções usadas

Requisitos de software e convenções de linha de comando Linux
Categoria Requisitos, convenções ou versão de software usada
Sistema Independente da distribuição Linux
Programas Linha de comando Bash, sistema baseado em Linux
Outro Qualquer utilidade que não esteja incluída no shell bash por padrão pode ser instalada usando sudo apt-get install utility-name (ou yum install para sistemas baseados em redhat)
Convenções # - requer que o Linux -Commands seja executado com privilégios de raiz diretamente como usuário root ou por uso de sudo comando
$-exige que o Linux-Commands seja executado como um usuário não privilegiado regular

Data básica

Estaremos usando o data comando para nossos horários. Especificamente, vamos usar data +%s Para obter o tempo em segundos desde a época, ou em outras palavras, o número de segundos desde 1970-01-01 00:00:00 UTC.

$ data +%s 1607481317 

O comando de data também pode fornecer precisão de nanossegundos (000000000… 9999999999), se seus horários precisarem ser super-precisos:

$ data +%s%n 1607488248328243029 

Discutir a implementação de nanossegundos precisos, está fora do escopo deste artigo, mas informe -nos se esse tópico interessa. A configuração seria muito semelhante à configuração demonstrada abaixo, com alguns cálculos e disposições extras para lidar com os segundos versus os milissegundos etc.

Exemplo 1: Um exemplo de tempo simples

Vamos começar com um exemplo fácil, onde vamos cronometrar um único comando, ou seja, sono 1, usando dois data +%s comandos e uma atribuição variável. Armazene o script abaixo em um arquivo chamado teste.sh:

#!/bin/Bash start = "$ (data +%s)" sono 1 duração = $ [$ (data +%s) - $ start] echo $ duração 
cópia de

Aqui, primeiro indicamos que queremos que o script seja executado como código Bash usando o #!/BIN/BASH Seleção de intérpretes. Nós também executamos chmod +x ./teste.sh Para fazer o script executável depois de criá -lo.

Em seguida, definimos a variável COMEÇAR para os segundos atuais desde a época da época, chamando uma subshell (como indicado por $ (…)) e dentro dessa subshell, executamos data +%s. Nós então usamos o dormir função para pausar nosso script por um segundo. Observe que o sono 1 Pode ser substituído pelo código do programa real, em outras palavras, a parte que você deseja tempo.

Finalmente definimos uma nova variável DURAÇÃO fazendo um cálculo (conforme indicado por $ […]) - ou seja, que levamos os segundos atuais desde a época (novamente usando data +%s de dentro de uma subshell) e depois subtrair o tempo de início do mesmo. O resultado é o número de segundos que passaram desde o início.

Quando executamos esse script, a saída é como esperado:

$ ./teste.SH 1 

Exemplo 2: Exemplo de tempo um pouco mais complexo

Desta vez, vamos expandir um pouco e tornar os horários mais modulares. Test2.sh:

#!/BIN/BASH START1 = "$ (data +%s)" Sleep 2 end1 = "$ (data +%s)" Sleep 2 start2 = "$ (data +%s)" sono 3 end2 = "$ (data + %s) "duração1 = $ [$ end1 - $ start1] duração2 = $ [$ end2 - $ start2] echo" a 1ª parte do código tomou: $ duration1 "echo" o 2ª parte do código levou: $ duration2 " 
cópia de

Aqui fizemos uma configuração semelhante ao primeiro exemplo, mas desta vez cronometramos dois comandos diferentes, usando um conjunto duplo de variáveis, e estruturamos as coisas um pouco mais usando um FIM variável para ambos os comandos. Nós também poderíamos ter escrito as últimas linhas de eco da seguinte maneira Test3.sh:

#!/BIN/BASH START1 = "$ (data +%s)" Sleep 2 end1 = "$ (data +%s)" Sleep 2 start2 = "$ (data +%s)" sono 3 end2 = "$ (data + %s) "Echo" A 1ª parte do código levou: $ [$ end1 - $ start1] "echo" A segunda parte do código levou: $ [$ end2 - $ start2] " 
cópia de

Como os dois DURAÇÃO Variáveis ​​eram de certa forma desnecessárias. O pode ter deixado o código mais claro para ler, mas eles não cumprem outra função real, ao contrário do COMEÇAR e FIM variáveis ​​usadas para cálculos reais.

Observe no entanto que não poderíamos ter escrito Test4.sh:

#!/BIN/BASH START1 = "$ (data +%s)" Sono 2 Sono 2 start2 = "$ (data +%s)" Sleep 3 eco "A 1ª parte do código levou: $ [$ (data +%s ) - $ start1] "echo" A 2ª parte do código tomou: $ [$ (data +%s) - $ start2] " 
cópia de

Como a data capturada dentro da subshell é o momento em que o eco está sendo executado, os horários para ambos estariam desligados: os horários finais deveriam estar assumindo logo após os comandos relevantes.

Talvez pelo segundo momento, teria sido possível usar um data +%s Diretamente no Echo (como o primeiro eco, apenas levaria alguns milissegundos para executar, mesmo com a subshell e a data incluída), mas não é perfeita e definitivamente não funcionaria se o tempo de precisão de nanossegundos for necessário. Também não é codificação limpa e mais difícil de ler/entender.

Vamos executar esses scripts e comparar a saída:

$ ./test2.A 1ª parte do Código tomou: 2 A 2ª parte do Código levou: 3 $ ./test3.A 1ª parte do Código tomou: 2 A 2ª parte do Código levou: 3 $ ./test4.A 1ª parte do Código tomou: 7 A 2ª parte do Código tomou: 3 

O Test2.sh e Test3.sh relataram horários corretos, como esperado. O Test4.sh Script relatou horários incorretos, também como esperado.

Você pode ver quanto tempo o script foi executado em geral, aproximadamente em segundos, independentemente de quaisquer horários? Se você responder, foi seis segundos, você está correto. Você pode ver como em Test2.sh e Test3.sh há um adicional sono 2 que não está sendo captura nos comandos de tempo. Isso exemplifica como você pode cronometrar várias seções de código.

Exemplo 3: Timers sobrepostos

Vamos agora olhar para um exemplo final que tem temporizadores e vezes sobrepostos uma função.Test5.sh:

#!/bin/bash my_sleep_function () sleep 1 geral_start = "$ (data +%s)" function_start = "$ (data +%s)" my_sleep_function function_end = "$ (data +%s)" sono 2 geral_end = " $ (data +%s) "echo" A parte da função do código levou: $ [$ function_end - $ function_start] segundos para executar "echo" o código geral tomou: $ [$ geral_end - $  Geral_start] segundos para executar " 
cópia de

Aqui definimos uma função my_sleep_function que simplesmente dorme por um segundo. Em seguida, definimos um cronômetro de início geral usando o Geral_start variável e novamente nosso data +%s em uma subshell. Em seguida, começamos outro cronômetro (o cronômetro de função com base no Function_start variável). Executamos a função e terminamos imediatamente o timer de função, definindo o Function_end variável.

Nós então fazemos um adicional sono 2 e então termine o cronômetro geral definindo o Geral_end cronômetro. Finalmente, produzimos as informações em um bom formato perto do final do script. Os dois eco As declarações não fazem parte do tempo, mas o tempo de execução deles seria mínimo; Normalmente, estamos tentando o tempo de várias e específicas seções de nosso código, que tendem a ter longas durações, como laços extensos, chamadas de programa externas, muitas subs -grandes etc.

Vamos olhar para fora de Test5.sh:

$ ./test5.A parte da função do código levou: 1 segundos para executar o código geral levou: 3 segundos para executar 


Parece bom. O script cronometrou corretamente a função para 1 segundo e o tempo de execução geral do script como 3 segundos, sendo a combinação da chamada de função e o sono extra de dois segundos.

Observe que, se a função for recursivamente, pode fazer sentido usar uma variável de tempo global adicional à qual o tempo de execução da função pode ser adicionado ao. Você também pode contar o número de chamadas de funções e, no final, dividir o número de chamadas de função usando bc (Ref como fazer cálculos decimais em Bash usando BC). Neste caso de uso, pode ser melhor mover os temporizadores de início e parar, bem como o cálculo da duração da função para dentro da função. Faz um código mais limpo e claro e pode eliminar a duplicação desnecessária de código.

Conclusão

Neste artigo, analisamos o cronometrar várias partes do nosso código de script bash usando data +%s como base para obter segundos desde o tempo da época, bem como uma ou mais atribuições variáveis ​​para calcular os horários de desempenho uma ou mais seções do código. Usando esses blocos básicos de construção, pode -se fazer estruturas complexas de medição de tempo, por função, por script chamado ou até temporizadores que se sobrepõem (por exemplo, um por script, bem como um por função etc.) usando diferentes variáveis. Aproveitar!

Se você estiver interessado em aprender mais sobre Bash, consulte nossa série útil de dicas e truques de linha de comando bash.

Tutoriais do Linux relacionados:

  • Como construir um aplicativo Tknter usando um objeto orientado…
  • Tutorial de depuração do GDB para iniciantes
  • Expressões regulares do Python com exemplos
  • Bash Regex avançado com exemplos
  • Loops aninhados em scripts de basquete
  • Bash Loops com exemplos
  • Como trabalhar com a API de Rest WooCommerce com Python
  • Instale Arch Linux na estação de trabalho VMware
  • Como configurar um servidor OpenVPN no Ubuntu 20.04
  • Bash idiomas variáveis ​​avançados para sensibilidade ao caso…