web-dev-qa-db-fra.com

Comment obtenir efficacement le temps d'exécution d'un script?

Je voudrais afficher l'heure de fin d'un script.

Ce que je fais actuellement, c'est -

#!/bin/bash
date  ## echo the date at start
# the script contents
date  ## echo the date at end

Cela montre simplement l'heure de début et de fin du script. Serait-il possible d'afficher une sortie à grain fin comme le temps processeur/temps io, etc.?

392
mtk

Utilisez simplement time lorsque vous appelez le script:

time yourscript.sh
506
Trudbert

Si time n'est pas une option,

start=`date +%s`
stuff
end=`date +%s`

runtime=$((end-start))
204
Rob Bos

Appelez simplement times sans arguments à la sortie de votre script.

Avec ksh ou zsh, vous pouvez également utiliser time à la place. Avec zsh, time vous donnera également l'heure de l'horloge murale en plus de l'utilisateur et système temps CPU.

Pour conserver le statut de sortie de votre script, vous pouvez le faire:

ret=$?; times; exit "$ret"

Ou vous pouvez également ajouter un piège sur EXIT:

trap times EXIT

De cette façon, les heures seront appelées à chaque sortie du shell et le statut de sortie sera préservé.

$ bash -c 'trap times EXIT; : {1..1000000}'
0m0.932s 0m0.028s
0m0.000s 0m0.000s
$ zsh -c 'trap time EXIT; : {1..1000000}'
Shell  0.67s user 0.01s system 100% cpu 0.677 total
children  0.00s user 0.00s system 0% cpu 0.677 total

Notez également que tous les bash, ksh et zsh ont un $SECONDS variable spéciale qui est automatiquement incrémentée toutes les secondes. Dans les deux zsh et ksh93, cette variable peut également être rendue à virgule flottante (avec typeset -F SECONDS) pour obtenir plus de précision. Ce n'est que l'heure de l'horloge murale, pas le temps CPU.

77
Stéphane Chazelas

Je suis un peu en retard dans le train en marche, mais je voulais publier ma solution (pour une précision inférieure à la seconde) au cas où d'autres tomberaient sur ce fil lors de la recherche. La sortie est au format jours, heures, minutes et enfin secondes:

res1=$(date +%s.%N)

# do stuff in here

res2=$(date +%s.%N)
dt=$(echo "$res2 - $res1" | bc)
dd=$(echo "$dt/86400" | bc)
dt2=$(echo "$dt-86400*$dd" | bc)
dh=$(echo "$dt2/3600" | bc)
dt3=$(echo "$dt2-3600*$dh" | bc)
dm=$(echo "$dt3/60" | bc)
ds=$(echo "$dt3-60*$dm" | bc)

LC_NUMERIC=C printf "Total runtime: %d:%02d:%02d:%02.4f\n" $dd $dh $dm $ds

J'espère que quelqu'un trouvera cela utile!

32
jwchew

Ma méthode pour bash:

# Reset BASH time counter
SECONDS=0
    # 
    # do stuff
    # 
ELAPSED="Elapsed: $(($SECONDS / 3600))hrs $((($SECONDS / 60) % 60))min $(($SECONDS % 60))sec"
23
Mark

Cette question est assez ancienne, mais en essayant de trouver ma façon préférée de le faire, ce fil est venu haut ... et je suis surpris que personne ne l'ait mentionné:

perf stat -r 10 -B sleep 1

'perf' est un outil d'analyse des performances inclus dans le noyau sous 'tools/perf' et souvent disponible pour être installé dans un paquet séparé ('perf' dans CentOS et 'linux-tools' sur Debian/Ubuntu). Le wiki Linux Kernal perf a beaucoup plus d'informations à ce sujet.

L'exécution de "perf stat" donne beaucoup de détails, y compris le temps d'exécution moyen juste à la fin:

1.002248382 seconds time elapsed                   ( +-  0.01% )
8
Zaahid
#!/bin/bash
start=$(date +%s.%N)

# HERE BE CODE

end=$(date +%s.%N)    
runtime=$(python -c "print(${end} - ${start})")

echo "Runtime was $runtime"

Oui, cela appelle Python, mais si vous pouvez vivre avec cela, alors c'est une solution plutôt agréable et laconique.

6
Alex

Une petite fonction Shell qui peut être ajoutée avant les commandes pour mesurer leur temps:

tm() {
  local start=$(date +%s)
  $@
  local exit_code=$?
  echo >&2 "took ~$(($(date +%s)-${start})) seconds. exited with ${exit_code}"
  return $exit_code
}

Ensuite, utilisez-le dans votre script ou sur votre ligne de commande comme ceci:

tm the_original_command with all its parameters
5
Evgeny

Personnellement, j'aime envelopper tout mon code de script dans une fonction "principale" comme ceci:

main () {
 echo running ...
}

# stuff ...

# calling the function at the very end of the script
time main

Remarquez à quel point il est facile d'utiliser la commande time dans ce scénario. Évidemment, vous ne mesurez pas le temps précis, y compris le temps d'analyse du script, mais je le trouve suffisamment précis dans la plupart des situations.

5
LeZuse

En utilisant niquement bash, il est également possible de mesurer et calculer la durée d'une partie du script Shell (ou le temps écoulé pour l'ensemble du script):

start=$SECONDS

... # do time consuming stuff

end=$SECONDS

vous pouvez maintenant soit imprimer la différence:

echo "duration: $((end-start)) seconds."

si vous avez seulement besoin d'une durée incrémentielle, faites:

echo "duration: $((SECONDS-start)) seconds elapsed.."

Vous pouvez également stocker la durée dans une variable:

let diff=end-start
3
gauteh

Voici une variante de la réponse d'Alex. Je ne me soucie que des minutes et des secondes, mais je voulais aussi qu'il soit formaté différemment. J'ai donc fait ceci:

start=$(date +%s)
end=$(date +%s)
runtime=$(python -c "print '%u:%02u' % ((${end} - ${start})/60, (${end} - ${start})%60)")
3
mpontillo
#!/bin/csh
#PBS -q glean
#PBS -l nodes=1:ppn=1
#PBS -l walltime=10:00:00
#PBS -o a.log
#PBS -e a.err
#PBS -V
#PBS -M [email protected]
#PBS -m abe
#PBS -A k4zhang-group
START=$(date +%s)
for i in {1..1000000}
do
echo 1
done
END=$(date +%s)
DIFF=$(echo "$END - $START" | bc)
echo "It takes DIFF=$DIFF seconds to complete this task..."
3
Shicheng Guo

La fonction de synchronisation basée sur SECONDS, limitée à la granularité de second niveau uniquement, n'utilise aucune commande externe:

time_it() {
  local start=$SECONDS ts ec
  printf -v ts '%(%Y-%m-%d_%H:%M:%S)T' -1
  printf '%s\n' "$ts Starting $*"
  "$@"; ec=$?
  printf -v ts '%(%Y-%m-%d_%H:%M:%S)T' -1
  printf '%s\n' "$ts Finished $*; elapsed = $((SECONDS-start)) seconds"
  # make sure to return the exit code of the command so that the caller can use it
  return "$ec"
}

Par exemple:

time_it sleep 5

donne

2019-03-30_17:24:37 Starting sleep 5 2019-03-30_17:24:42 Finished
sleep 5; elapsed = 5 seconds
2
codeforester
#!/bin/bash
begin=$(date +"%s")

Script

termin=$(date +"%s")
difftimelps=$(($termin-$begin))
echo "$(($difftimelps / 60)) minutes and $(($difftimelps % 60)) seconds elapsed for Script Execution."
1
Arun Binoy

Pour bash, utilisez la variable interne $SECONDS. Voici une démo:

Notez que dt_min Est arrondi de 0.01666666666... (1 seconde = autant de minutes) à 0.017 Dans ce cas puisque j'utilise la fonction printf pour arrondir . La partie sleep 1; Ci-dessous est l'endroit où vous appelleriez votre script pour exécuter et chronométrer, mais je dors juste pendant 1 seconde à la place de cette démo:

start=$SECONDS; sleep 1; end=$SECONDS; dt_sec=$(( end - start )); dt_min=$(printf %.3f $(echo "$dt_sec/60" | bc -l)); echo "dt_sec = $dt_sec; dt_min = $dt_min"
dt_sec = 1; dt_min = 0.017

En relation:

0
Gabriel Staples