Ich möchte herausfinden, wie viele Millisekunden eine bestimmte Funktion verwendet. Also sah ich hoch und niedrig aus, konnte aber keinen Weg finden, die Zeit in Ruby mit Millisekundengenauigkeit zu erfassen.
Wie machst Du das? In den meisten Programmiersprachen ist es einfach so
start = now.milliseconds
myfunction()
end = now.milliseconds
time = end - start
Sie können auch die integrierte Funktion Benchmark.measure verwenden:
require "benchmark" puts(Benchmark.measure { sleep 0.5 })
Drucke:
0.000000 0.000000 0.000000 ( 0.501134)
quelle
0.000000
)? Update: Sah es bis in die Dokumentation und es ist Benutzer - CPU - Zeit, System - CPU - Zeit, und die Summe der beiden letztgenannten.Benchmark.bm
. Es ist nützlich zu sehen, wo die Zeit manchmal verbracht wird. Hier können Sie sehen, dass der Block nur im Leerlauf ist (0 insgesamt, 0,5 real)Benchmark.realtime
der einen einzigen verständlichen Schwimmer zurückgibt :)Die Verwendung
Time.now
(die die Wanduhrzeit zurückgibt) als Basislinie weist einige Probleme auf, die zu unerwartetem Verhalten führen können. Dies wird durch die Tatsache verursacht , dass die Zeit Wanduhr unterliegt Änderungen wie eingefügten Schaltsekunden oder Zeitschwenk die lokale Zeit zu einer Referenzzeit einzustellen.Wenn während der Messung beispielsweise eine Schaltsekunde eingefügt wird, wird diese um eine Sekunde ausgeschaltet. Abhängig von den örtlichen Systembedingungen müssen Sie sich möglicherweise mit Sommerzeit, schnelleren oder langsamer laufenden Uhren oder sogar einem Zeitsprung der Uhr auseinandersetzen, was zu einer negativen Dauer und vielen anderen Problemen führt.
Eine Lösung für dieses Problem besteht darin, eine andere Uhrzeit zu verwenden: eine monotone Uhr. Dieser Uhrentyp hat andere Eigenschaften als die Wanduhr. Es erhöht sich monitonisch, dh es geht nie zurück und nimmt mit konstanter Geschwindigkeit zu. Damit stellt es nicht die Wanduhr dar (dh die Zeit, die Sie von einer Uhr an Ihrer Wand lesen), sondern einen Zeitstempel, den Sie mit einem späteren Zeitstempel vergleichen können, um einen Unterschied zu erhalten.
In Ruby können Sie einen solchen Zeitstempel
Process.clock_gettime(Process::CLOCK_MONOTONIC)
wie folgt verwenden:t1 = Process.clock_gettime(Process::CLOCK_MONOTONIC) # => 63988.576809828 sleep 1.5 # do some work t2 = Process.clock_gettime(Process::CLOCK_MONOTONIC) # => 63990.08359163 delta = t2 - t1 # => 1.5067818019961123 delta_in_milliseconds = delta * 1000 # => 1506.7818019961123
Das
Process.clock_gettime
Methode gibt einen Zeitstempel als Float mit Sekundenbruchteilen zurück. Die tatsächlich zurückgegebene Nummer hat keine definierte Bedeutung (auf die Sie sich verlassen sollten). Sie können jedoch sicher sein, dass der nächste Anruf eine größere Nummer zurückgibt, und durch Vergleichen der Werte können Sie den Echtzeitunterschied ermitteln.Diese Attribute machen die Methode zu einem Hauptkandidaten für die Messung von Zeitunterschieden, ohne dass Ihr Programm in den ungünstigsten Zeiten fehlschlägt (z. B. um Mitternacht an Silvester, wenn eine weitere Schaltsekunde eingefügt wird).
Die
Process::CLOCK_MONOTONIC
hier verwendete Konstante ist auf allen modernen Linux-, BSD- und macOS-Systemen sowie auf dem Linux-Subsystem für Windows verfügbar. Es ist jedoch noch nicht für "rohe" Windows-Systeme verfügbar. Dort können Sie denGetTickCount64
Systemaufruf verwenden, der stattdessenProcess.clock_gettime
auch einen Zeitgeberwert in Millisekunden-Granularität unter Windows zurückgibt (> = Windows Vista, Windows Server 2008).Mit Ruby können Sie diese Funktion folgendermaßen aufrufen:
require 'fiddle' # Get a reference to the function once GetTickCount64 = Fiddle::Function.new( Fiddle.dlopen('kernel32.dll')['GetTickCount64'], [], -Fiddle::TYPE_LONG_LONG # unsigned long long ) timestamp = GetTickCount64.call / 1000.0 # => 63988.576809828
quelle
Sie sollten sich das Benchmark-Modul ansehen, um Benchmarks durchzuführen. Als schnelle und schmutzige Timing-Methode können Sie jedoch Folgendes verwenden:
def time now = Time.now.to_f yield endd = Time.now.to_f endd - now end
Beachten Sie die Verwendung von
Time.now.to_f
, die im Gegensatz zu to_i nicht auf Sekunden gekürzt wird.quelle
end
es ein Schlüsselwort ist.end_time
oder so, nicht nur falsch geschriebene Wörter, das ist höllisch schlampigVerwenden Sie Time.now.to_f
quelle
Der
absolute_time
Edelstein ist ein Ersatz für Benchmark, verwendet jedoch native Anweisungen, um weitaus genauer zu sein.quelle
Wir können auch eine einfache Funktion erstellen, um jeden Codeblock zu protokollieren:
def log_time start_at = Time.now yield if block_given? execution_time = (Time.now - start_at).round(2) puts "Execution time: #{execution_time}s" end log_time { sleep(2.545) } # Execution time: 2.55s
quelle
Wenn du benutzt
Sie erhalten Zeit in Sekunden, was alles andere als genau ist, insbesondere wenn Sie kleine Codestücke zeitlich festlegen.
quelle
Die Verwendung der
Time.now.to_i
Rückgabe der zweiten verging ab 1970/01/01. Wenn Sie das wissen, können Sie es tunDamit haben Sie einen Unterschied in der zweiten Größe. Wenn Sie es in Millisekunden möchten , fügen Sie es einfach dem Code hinzu
diff = diff * 1000
quelle
.to_i
gibt eine ganze Zahl an und würde die Millisekunden abschneiden. Dies würde funktionieren, wenn Sie es nur in ändern.to_f
Ich habe ein Juwel, das Ihre Ruby-Methode (Instanz oder Klasse) profilieren kann - https://github.com/igorkasyanchuk/benchmark_methods .
Kein Code mehr wie dieser:
Jetzt können Sie tun:
benchmark :calculate_report # in class
Und rufen Sie einfach Ihre Methode auf
quelle