Pour comparer des temps d'exécution de scripts entre différentes coquilles, certaines réponses SE suggèrent à l'aide de bash
'S intégrétime
commande, comme:
time bash -c 'foo.sh'
time dash -c 'foo.sh'
... etc, pour chaque coquille à tester. De tels repères ne parviennent pas à éliminer le temps pris pour chaque coquille pour charger et initialiser elle-même. Par exemple, supposons que les deux commandes ci-dessus étaient stockées sur n périphérique lent à la vitesse de lecture d'une disquette anticipée , (124 kb/s), dash
(A ~ 150k exécutable) chargerait environ 7x plus rapide que bash
( ~ 1m), le temps de chargement de la coquille obligeait Les numéros time
- Les temps de chargement de ces coquilles étant non pertinents pour mesurer les temps d'exécution de foo.sh
sous chaque coquille après Les coquilles ont été chargées.
Quel est le meilleur util portable et général à exécuter pour le timing de script pouvant être exécuté de dans chaque coquille? Donc, le code ci-dessus ressemblerait à quelque chose comme:
bash -c 'general_timer_util foo.sh'
dash -c 'general_timer_util foo.sh'
NB: Pas de shell intégrétime
commandes, car aucun n'est portable ou général.
Mieux encore, si l'util est également capable de comparer le temps pris par les commandes et les pipelines internes d'une coque, sans que l'utilisateur n'envoie d'abord à les emballer dans un script. La syntaxe artificielle comme cela aiderait:
general_timer_util "while read x ; do echo x ; done < foo"
Certaines coquilles 'time
peuvent gérer cela. Par example bash -c "time while false ; do : ; done"
travaux. Pour voir ce qui fonctionne, (et non), sur votre système essaie:
tail +2 /etc/shells |
while read s ; do
echo $s ; $s -c "time while false ; do : ; done" ; echo ----
done
J'utilise le [~ # ~ # ~] gnu [~ # ~ ~]date
commande, qui prend en charge une minuterie haute résolution:
START=$(date +%s.%N)
# do something #######################
"$@" &> /dev/null
#######################################
END=$(date +%s.%N)
DIFF=$( echo "scale=3; (${END} - ${START})*1000/1" | bc )
echo "${DIFF}"
Et puis j'appelle le script comme celui-ci:
/usr/local/bin/timing Dig +short unix.stackexchange.com
141.835
L'unité de sortie est en millisecondes.
L'utilitaire time
est généralement intégré à la coquille, comme vous l'avez remarqué, ce qui le rend inutile comme une minuterie "neutre".
Cependant, l'utilité est généralement également disponible en tant qu'utilisation externe, /usr/bin/time
, cela pourrait bien être utilisé pour effectuer les expériences de synchronisation que vous proposez.
$ bash -c '/usr/bin/time foo.sh'
Voici une solution qui:
éliminer [s] le temps pris pour chaque coquille pour charger et s'initialiser
peut être exécuté de dans chaque coquille
no Shell intégré
time
commandes, car aucun n'est portable ou général
Il y a deux parties: un programme C court couvrant gettimeofday
, qui est obsolète mais toujours plus portable que clock_gettime
, et un script short shell qui utilise ce programme pour obtenir une horloge de précision microsecondes de lecture des deux côtés de l'approvisionnement d'un script. Le programme C est le seul moyen portable et minimal de la hauteur d'une sous-deuxième précision sur un horodatage.
Voici le programme C Epoch.c
:
#include <sys/time.h>
#include <stdio.h>
int main(int argc, char **argv) {
struct timeval time;
gettimeofday(&time, NULL);
printf("%li.%06i", time.tv_sec, time.tv_usec);
}
Et le script shell timer
:
#!/bin/echo Run this in the Shell you want to test
START=$(./Epoch)
. "$1"
END=$(./Epoch)
echo "$END - $START" | bc
Ceci est standard langage de commande shell et bc
et doit fonctionner comme script sous Toute coque compatible POSIX.
Vous pouvez utiliser ceci comme suit:
$ bash timer ./test.sh
.002052
$ dash timer ./test.sh
.000895
$ zsh timer ./test.sh
.000662
Il ne mesède pas le système ou l'utilisation de l'utilisateur, seule une horloge murale non monotonique écoulée. Si l'horloge système change pendant l'exécution du script, cela donnera des résultats incorrects. Si le système est sous charge, le résultat ne sera pas fiable. Je ne pense pas que rien de mieux puisse être portable entre les coquilles.
Un script de minuterie modifié pourrait utiliser eval
au lieu de lancer des commandes en dehors d'un script.
Plusieurs fois la solution révisée à l'aide de /proc/uptime
et dc
/bc
/awk
en grandes parties grâce à l'entrée par AGC :
#!/bin/sh
read -r before _ < /proc/uptime
sleep 2s # do something...
read -r after _ < /proc/uptime
duration=$(dc -e "${after} ${before} - n")
# Alternative using bc:
# duration=$(echo "${after} - ${before}" | bc)
# Alternative using awk:
# duration=$(echo "${after} ${before}" | awk '{print $1 - $2}')
echo "It took $duration seconds."
Suppose évidemment que /proc/uptime
existe et a une certaine forme.