Gibt es in Linux einen Shell-Befehl, um die Zeit in Millisekunden zu erhalten?
Antworten
Zu viele Anzeigen?Reine Bash-Lösung
Seit bash
5.0 (veröffentlicht am 7. Januar 2019) können Sie die integrierte Variable EPOCHREALTIME
verwenden, die die Sekunden seit der Epoche enthält, einschließlich Dezimalstellen mit Mikrosekundenpräzision (echo $EPOCHREALTIME
zeigt etwas wie 1547624774.371210
). Durch Entfernen des .
und der letzten drei Stellen erhalten wir Millisekunden:
Entweder verwenden Sie
(( t = ${EPOCHREALTIME/./} / 1000 ))
oder so etwas wie
t=${EPOCHREALTIME/./} # Entferne den Punkt (s µs)
t=${t%???} # Entferne die letzten drei Ziffern (µs ms)
In jedem Fall wird t
etwas wie 1547624774371
sein.
Die anderen Antworten sind wahrscheinlich in den meisten Fällen ausreichend, aber ich dachte, ich würde meine zwei Cent hinzufügen, da ich auf einem BusyBox System auf ein Problem gestoßen bin.
Das fragliche System unterstützte die Formatoption %N
nicht und verfügt über keinen Python- oder Perl-Interpreter.
Nach viel Kopfzerbrechen sind wir (Danke Dave!) zu folgendem gekommen:
adjtimex | awk '/(time.tv_sec|time.tv_usec):/ { printf("%06d", $2) }'
Es extrahiert die Sekunden und Mikrosekunden aus der Ausgabe von adjtimex
(normalerweise zur Einstellung von Optionen für die Systemuhr verwendet) und druckt sie ohne Zeilenumbrüche aus (damit sie zusammengeklebt werden). Beachten Sie, dass das Mikrosekundenfeld mit Nullen vorbelegt werden muss, diesbeeinflusst jedoch nicht das Sekundenfeld, das sowieso länger als sechs Stellen ist. Es sollte also trivial sein, Mikrosekunden in Millisekunden umzuwandeln.
Wenn Sie einen nachgestellten Zeilenumbruch benötigen (vielleicht weil es besser aussieht), probieren Sie dies:
adjtimex | awk '/(time.tv_sec|time.tv_usec):/ { printf("%06d", $2) }' && printf "\n"
Beachten Sie auch, dass dies adjtimex
und awk
voraussetzt. Wenn nicht, dann können Sie mit BusyBox lokal darauf verweisen:
ln -s /bin/busybox ./adjtimex
ln -s /bin/busybox ./awk
Und rufen Sie dies dann wie folgt auf:
./adjtimex | ./awk '/(time.tv_sec|time.tv_usec):/ { printf("%06d", $2) }'
Oder Sie könnten sie natürlich in Ihren PATH
setzen.
EDIT:
Das oben erwähnte funktionierte auf meinem BusyBox-Gerät. Auf Ubuntu habe ich dasselbe versucht und festgestellt, dass adjtimex
unterschiedliche Versionen hat. Auf Ubuntu hat dies funktioniert, um die Zeit in Sekunden mit Dezimalstellen bis Mikrosekunden (einschließlich eines nachgestellten Zeilenwechsels) auszugeben.
sudo apt-get install adjtimex
adjtimex -p | awk '/raw time:/ { print $6 }'
Auf Ubuntu würde ich das jedoch nicht tun. Ich würde date +%s%N
verwenden.
date
Befehl hat keine Millisekunden auf OS X geliefert, daher wurde ein Alias aus Python verwendet
millis(){ python -c "import time; print(int(time.time()*1000))"; }
ODER
alias millis='python -c "import time; print(int(time.time()*1000))"'
BEARBEITEN: Nach Kommentar von @CharlesDuffy. Das Starten eines Kindprozesses dauert zusätzliche Zeit.
$ time date +%s%N
1597103627N
date +%s%N 0.00s Benutzer 0.00s System 63% CPU 0.006 gesamt
Python verbessert immer noch die Startzeit der VM, und ist nicht so schnell wie vorab kompilierter Code (wie date
).
Auf meinem Rechner dauerte es etwa 30ms - 60ms (das sind 5x-10x der 6ms, die date
benötigt)
$ time python -c "import time; print(int(time.time()*1000))"
1597103899460
python -c "import time; print(int(time.time()*1000))" 0.03s Benutzer 0.01s System 83% CPU 0.053 gesamt
Ich habe festgestellt, dass awk
leichter ist als python
, daher benötigt awk
im Bereich von 6ms bis 12ms (d.h. 1x bis 2x von date
):
$ time awk '@load "time"; BEGIN{print int(1000 * gettimeofday())}'
1597103729525
awk '@load "time"; BEGIN{print int(1000 * gettimeofday())}' 0.00s Benutzer 0.00s System 74% CPU 0.010 gesamt
Ich wollte nur zu Alpers Antwort hinzufügen, was ich tun musste, um das Ganze zum Laufen zu bringen:
Auf dem Mac benötigen Sie brew install coreutils
, damit wir gdate
verwenden können. Andernfalls auf Linux ist es einfach date
. Und diese Funktion hilft Ihnen, Befehle zu timen, ohne temporäre Dateien oder ähnliches erstellen zu müssen:
function timeit() {
start=`gdate +%s%N`
bash -c $1
end=`gdate +%s%N`
runtime=$(((end-start)/1000000000.0))
echo " Sekunden"
}
Und Sie können es mit einem String verwenden:
timeit 'tsc --noEmit'