Measure and Benchmark Time for Ruby Methods

放肆的年华 提交于 2019-12-03 03:05:00

问题


How can i measure the time taken by a method and the individual statements in that method in Ruby. If you see the below method i want to measure the total time taken by the method and the time taken for database access and redis access. I do not want to write Benchmark.measure before every statement. Does the ruby interpreter gives us any hooks for doing this ?

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

回答1:


You could use the Time object. (Time Docs)

For example,

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

diff = finish - start

diff would be in seconds, as a floating point number.

EDIT: end is reserved.




回答2:


The simplest way:

require 'benchmark'

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

Sample output:

2.2.3 :001 > foo
  5.230000   0.020000   5.250000 (  5.274806)

Values are: cpu time, system time, total and real elapsed time.

Source: ruby docs.




回答3:


Use Benchmark's Report

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

This will output something like the following:

                        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: This is not shown in output.

More information can be found here.




回答4:


A second thought, define the measure() function with Ruby code block argument can help simplify the time measure code:

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



回答5:


Many of the answers suggest the use of Time.now. But it is worth being aware that Time.now can change. System clocks can drift and might get corrected by the system's administrator or via NTP. It is therefore possible for Time.now to jump forward or back and give your benchmarking inaccurate results.

A better solution is to use the operating system's monotonic clock, which is always moving forward. Ruby 2.1 and above give access to this via:

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

You can read more details here. Also you can see popular Ruby project, Sidekiq, made the switch to monotonic clock.




回答6:


Look into the ruby-prof package, it should have what you need. It will create huge call stacks with timings.

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

It might be too granular, in which case just wrapping bigger sections in Benchmark.measure might be a good way to go.




回答7:


In the spirit of wquist's answer, but a little simpler, you could also do it like below:

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


来源:https://stackoverflow.com/questions/11406410/measure-and-benchmark-time-for-ruby-methods

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!