Pour comparer les temps d'exécution des scripts entre différents shells, certaines réponses SE suggèrent d'utiliser bash
la commande intégrée de time
, comme ceci:
time bash -c 'foo.sh'
time dash -c 'foo.sh'
... etc , pour chaque shell à tester. Ces critères de référence ne parviennent pas à éliminer le temps nécessaire pour chaque coquille charger et initialiser lui - même . Par exemple, supposons que les deux commandes ci-dessus aient été stockées sur un périphérique lent avec la vitesse de lecture d'une disquette ancienne , (124 Ko / s), dash
(un exécutable de ~ 150 Ko) se chargerait environ 7 fois plus rapidement que bash
( ~ 1 M ), le shell le temps de chargement fausserait les time
chiffres - les temps de préchargement de ces réservoirs étant sans rapport avec la mesure des durées de fonctionnement de foo.sh
chaque coquille après le chargement des réservoirs.
Quelle est la meilleure utilisation portable et générale à exécuter pour la synchronisation des scripts qui peut être exécutée à partir de chaque shell? Ainsi, 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 time
commandes intégrées au shell , car aucune n'est portable ou générale.
Mieux encore si l'utilitaire est également capable de comparer le temps pris par les commandes internes et les pipelines d'un shell, sans que l'utilisateur n'ait à les emballer au préalable dans un script. Une syntaxe artificielle comme celle-ci aiderait:
general_timer_util "while read x ; do echo x ; done < foo"
Certains obus time
peuvent gérer cela. Par exemple bash -c "time while false ; do : ; done"
fonctionne. Pour voir ce qui fonctionne (et ne fonctionne pas) sur votre système, essayez:
tail +2 /etc/shells |
while read s ; do
echo $s ; $s -c "time while false ; do : ; done" ; echo ----
done
/usr/bin/time
?Réponses:
Vous devriez noter que
time
c'est spécifié par POSIX , et AFAICT la seule option que POSIX mentionne (-p
) est prise en charge correctement par divers shells:la source
time
. C'est comparable à laisser les sprinters mesurer leur propre temps sur 100m, individuellement, au lieu de le faire avec une horloge à la fois. C'est évidemment un peu marrant, mais quand même ...time
n'était pas portable; il semble portable. (Je suis d'accord avec votre point sur la comparabilité, cependant)dash -c 'time -p while false ; do : ; done'
retourne "heure: ne peut pas s'exécuter pendant: aucun fichier ou répertoire <cr> Commande sortie avec des états non nuls 127" .J'utilise la commande GNU
date
, qui prend en charge une minuterie haute résolution:Et puis j'appelle le script comme ceci:
L'unité de sortie est en millisecondes.
la source
date
spécifiquement GNU .START
et où elleEND
est définie, cela affecterait évidemment votre résultat. Je ne sais pas à quel point vous en avez besoin et si c'est important dans votre cas, mais comme je l'ai dit, quelque chose à garder à l'esprit. (Histoire amusante: je connais un logiciel où exactement il a conduit à des résultats négatifs inattendus - il a été utilisé pour effectuer des calculs - qui ont ensuite cassé quelques choses.)L'
time
utilitaire est généralement intégré au shell, comme vous l'avez remarqué, ce qui le rend inutile en tant que temporisateur "neutre".Cependant, l'utilitaire est généralement également disponible en tant qu'utilitaire externe
/usr/bin/time
, qui peut très bien être utilisé pour effectuer les expériences de synchronisation que vous proposez.la source
foo.sh
est exécutable et possède un shebang, alors cela l'exécute toujours avec le même shell, et il compte le temps de démarrage de ce shell, donc ce n'est pas ce que OP veut. S'il enfoo.sh
manque un, cela ne fonctionne pas du tout.time
", semble-t-il. Le temps de démarrage du shell peut devoir être mesuré séparément.time
commande intégrée. Cependant de nombreux shellsbash
ont notamment untime
mot-clé qui peut être utilisé pour chronométrer les pipelines. Pour désactiver ce mot clé afin que latime
commande (dans le système de fichiers) soit utilisée, vous pouvez le citer comme"time" foo.sh
. Voir aussi unix.stackexchange.com/search?q=user%3A22565+time+keywordVoici une solution qui:
Il y a deux parties: un programme C court qui se termine
gettimeofday
, qui est obsolète mais toujours plus portable queclock_gettime
, et un script shell court qui utilise ce programme pour obtenir une horloge de précision en microsecondes lisant les deux côtés de l'approvisionnement d'un script. Le programme C est le seul moyen portable et à surcharge minimale pour obtenir une précision d'une sous-seconde sur un horodatage.Voici le programme C
epoch.c
:Et le script shell
timer
:Ce standard langage de commande shell et
bc
et devrait fonctionner comme un script shell sous tout compatible POSIX.Vous pouvez l'utiliser comme:
Il ne mesure pas le temps système ou utilisateur, seulement le temps écoulé d'horloge murale non monotone. 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 quelque chose de mieux puisse être portable entre les coquilles.
Un script de minuterie modifié pourrait utiliser à la
eval
place pour exécuter des commandes en dehors d'un script.la source
eval
), je peaufinais le script dans la réponse de Rabin pour l'inclureeval "$@"
, afin qu'il puisse exécuter des buildins de shell à la volée.Solution révisée à plusieurs reprises utilisant
/proc/uptime
etdc
/bc
/awk
en grande partie grâce à l'entrée par agc :Suppose évidemment que cela
/proc/uptime
existe et a une certaine forme.la source
/proc
système de fichiers. Si c'est une préoccupation ou non, je ne sais pas.awk
peuvent être importants. Peut-êtreb=$(cat /proc/uptime)
avant, puisa=$(cat /proc/uptime)
après, puis analyser $ a et $ b et soustraire.read
sont meilleurs quecat
ça, ce serait plus propre (et un peu plus rapide):read before dummyvar < /proc/uptime ;sleep 2s;read after dummyvar < /proc/uptime; duration=$(dc -e "${after} ${before} - n");echo "It took $duration seconds."