Rails Benchmarking

So you want to know fast your Rails app is going?

If you just want to see how fast a bit of code is you can use the Benchmark module which is part of the Ruby Standard Library.

require 'benchmark'

puts Benchmark.measure { (0..9999999).each{|n| n * 99999999} }
#     user       system      total      real
# => 0.770000   0.010000   0.780000 (  0.773784)

If you want to compare two or more bits of Ruby code that do the same thing and see how fast they are against each other then you can use the ‘bm’ method on Benchmark.

require 'benchmark'

Benchmark.bm do |z|
  z.report { x = 0; (0..9999999).each{|n| x += n * 99999999} }
  z.report { x = (0..9999999).map{|n| n * 99999999}.sum }
  z.report { x = 0; for n in 0..9999999; x += n * 99999999; end }
end

#       user     system      total        real
#   1.441087   0.003661   1.444748 (  1.451196)
#   0.837622   0.039052   0.876674 (  0.880564)
#   1.555514   0.004319   1.559833 (  1.566806)

So for this code the second implementation is the fastest by a good margin, which might not have been my first guess.

You can also use the Benchmark method #bmbm to run the code in both rehearsal and then the real tests in case the benchmark results might be uneven because of garbage collection. Running it for the example above returns:

Benchmark.bmbm do |z|
  z.report { x = 0; (0..9999999).each{|n| x += n * 99999999} }
  z.report { x = (0..9999999).map{|n| n * 99999999}.sum }
  z.report { x = 0; for n in 0..9999999; x += n * 99999999; end }
end

Rehearsal ------------------------------------
   0.896595   0.000000   0.896595 (  0.896600)
   0.568865   0.007963   0.576828 (  0.576842)
   0.915542   0.000003   0.915545 (  0.915562)
--------------------------- total: 2.388968sec

       user     system      total        real
   0.877021   0.000008   0.877029 (  0.877058)
   0.566475   0.015973   0.582448 (  0.582493)
   0.905056   0.000000   0.905056 (  0.905080)

You can also measure methods and label the reports like so:

require 'benchmark'

def fast(range, multiple)
  return range.map{|n| n * multiple}.sum
end

def slow(range, multiple)
  x = 0
  for n in range
    x += n * multiple
  end
  return x
end

range = (0..9999999)
multiple = 99999999
Benchmark.bm do |z|
  z.report('Fast method - ') {fast(range, multiple)}
  z.report('Slow method - ') {slow(range, multiple)}
end

# =>                user     system      total        real
# Fast method -   0.573835   0.003838   0.577673 (  0.577681)
# Slow method -   0.908593   0.000827   0.909420 (  0.909443)

Processing…
Success! You're on the list.