webentwicklung-frage-antwort-db.com.de

Messen und Festlegen der Zeit für Ruby Methoden

Wie kann ich die von einer Methode benötigte Zeit und die einzelnen Anweisungen in dieser Methode in Ruby messen? Wenn Sie die folgende Methode sehen, möchte ich die Gesamtzeit messen, die die Methode benötigt, und die Zeit, die für den Datenbankzugriff und den erneuten Zugriff benötigt wird. Ich möchte Benchmark.measure nicht vor jeder Aussage schreiben. Gibt uns der Ruby Interpreter irgendwelche Haken dafür?

def foo
# code to access database
# code to access redis. 
end
72
Phani

Sie können das Objekt Time verwenden. ( Time Docs )

Beispielsweise,

start = Time.now
# code to time
finish = Time.now

diff = finish - start

diff würde als Gleitkommazahl in Sekunden angegeben.

EDIT: end ist reserviert.

101
wquist

Der einfachste Weg:

require 'benchmark'

def foo
 time = Benchmark.measure {
  code to test
 }
 puts time.real #or save it to logs
end

Beispielausgabe:

2.2.3 :001 > foo
  5.230000   0.020000   5.250000 (  5.274806)

Die Werte sind: CPU-Zeit, Systemzeit, Gesamtzeit und real verstrichene Zeit.

Quelle: Ruby-Dokumente .

83

Verwenden Sie den Benchmark-Bericht

require 'benchmark' # Might be necessary.

def foo
  Benchmark.bm(20) do |bm|  # The 20 is the width of the first column in the output.
    bm.report("Access Database:") do 
      # Code to access database.
    end

    bm.report("Access Redis:") do
      # Code to access redis.
    end
  end
end

Dadurch wird etwa Folgendes ausgegeben:

                        user     system      total        real
Access Database:    0.020000   0.000000   0.020000 (  0.475375)
Access Redis:       0.000000   0.000000   0.000000 (  0.000037)

<------ 20 ------->  # This is where the 20 comes in. NOTE: Not shown in output.

Weitere Informationen finden Sie hier .

25
Joshua Pinter

Ein zweiter Gedanke, definieren Sie die measure () -Funktion mit Ruby Codeblockargument kann helfen, den Zeitmesscode zu vereinfachen:

def measure(&block)
  start = Time.now
  block.call
  Time.now - start
end

# t1 and t2 is the executing time for the code blocks.
t1 = measure { sleep(1) }

t2 = measure do
  sleep(2)
end
6
Houcheng

Viele der Antworten deuten auf die Verwendung von Time.now. Aber es lohnt sich zu wissen, dass Time.now kann wechseln. Systemuhren können driften und werden möglicherweise vom Systemadministrator oder über NTP korrigiert. Es ist Time.now daher möglich, vorwärts oder rückwärts zu springen und Ihrem Benchmarking ungenaue Ergebnisse zu geben.

Eine bessere Lösung ist die Verwendung der monotonen Uhr des Betriebssystems, die sich immer weiterentwickelt. Ruby 2.1 und höher geben Zugriff darauf über:

start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
# code to time
finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
diff = finish - start # gets time is seconds as a float

Sie können mehr Details lesen hier . Sie können auch das beliebte Ruby Projekt Sidekiq sehen, das auf monotone Uhr umgestellt hat.

5
Guy C

Schau in das Ruby-prof Paket, sollte es haben, was Sie brauchen. Es werden riesige Callstacks mit Timings erstellt.

http://Ruby-prof.rubyforge.org/

Es ist möglicherweise zu detailliert. In diesem Fall werden nur größere Abschnitte in Benchmark.measure könnte ein guter Weg sein.

3
Cody Caughlan

Im Geiste von wquists Antwort , aber ein bisschen einfacher könnte man es auch so machen:

start = Time.now
# code to time
Time.now - start
2
ADude2