Measure and Benchmark Time for Ruby Methods

Measure user time or system time in Ruby without Benchmark or time

I re-read the Benchmark documentation and saw that it has a method named measure. This method does exactly what I want: Measure the time your code needs and returning an object which contains user time, system time, system time of childrens etc. It is as easy as

require 'benchmark'
measurement = Benchmark.measure do
# your code goes here
end

In the process I found out that you can add custom rows to the Benchmark output. You can use this to get the best of both worlds (custom time measurements and a nice output at the end) as follows:

require 'benchmark'

measurements = []
10.times { measurements << Benchmark.measure { 1_000_000.times { a = "1" } } }

# measurements.sum or measurements.inject(0){...} does not work, since the
# array contains Benchmark instances, which cannot be coerced into Fixnum's
# Array#sum will work if you are using Rails
sum = measurements.inject(nil) { |sum, t| sum.nil? ? sum = t : sum += t }
avg = sum / measurements.size

# 7 is the width reserved for the description "sum:" and "avg:"
Benchmark.bm(7, "sum:", "avg:") do |b|
[sum, avg]
end

The result will look like the following:

             user     system      total        real
sum: 2.700000 0.000000 2.700000 ( 2.706234)
avg: 0.270000 0.000000 0.270000 ( 0.270623)

Ruby on Rails' Method Benchmark Performance

You can use ruby benchmark module for this kind of test

require 'benchmark'
Benchmark.bm do |x|
x.report { User.count }
x.report { u = User.where(account_id: 5); u.count }
x.report { u = User.where(account_id: 5); u.map |a| a.account_id = 6 end }
end

What is an idiomatic way to measure time in Ruby?

A really idiomatic way would be to use the standard library. :)

require 'benchmark'

result = nil
elapsed = Benchmark.realtime do
result = do_something
end

Ruby Benchmarking a line that runs multiple times

There are many gems that might help depending on your application but you could try some of these:

https://github.com/flyerhzm/bullet

https://github.com/SamSaffron/memory_profiler

https://github.com/MiniProfiler/rack-mini-profiler

https://github.com/tmm1/stackprof

https://github.com/oozou/ruby-prof-flamegraph

Another crude approach might be to add a Logger and log before and after any line which you suspect might be time consuming.

Let's use ruby-prof-flamegraph example:

Install the gem:

gem install ruby-prof-flamegraph

And the example implementation:

#example.rb

require 'ruby-prof'
require 'ruby-prof-flamegraph'

rubyprof_dir = Gem::Specification.find_by_name('ruby-prof').gem_dir
require "#{rubyprof_dir}/test/prime"

# Profile the code
result = RubyProf.profile do
run_primes(200)
end

# Print a graph profile to text
printer = RubyProf::FlameGraphPrinter.new(result)
printer.print(STDOUT, {})

To generate the image:

bundle exec ruby example.rb | \
~/GitHub/FlameGraph/flamegraph.pl --countname=ms --width=728 > example.svg


Related Topics



Leave a reply



Submit