user3749140 user3749140 - 1 year ago 74
Ruby Question

Benchmarking methods in Ruby

I am trying to benchmark a set of computations like so -

def benchmark(func, index, array)
start =
func(index, array)
start - #returns time taken to perform func

def func1(index, array)
#perform computations based on index and array

def func2(index, array)
#more computations....

benchmark(func1, index1, array1)
benchmark(func1, index2, array2)

Now I'm wondering how can I achieve this. I tried this example, but is spits out

`func1': wrong number of arguments (0 for 2) (ArgumentError)

If I try -

benchmark(func1(index1, array1), index1, array1)

It spits out...

undefined method `func' for main:Object (NoMethodError)

I saw a similar question asked about it, but it was for python. Passing functions with arguments to another function in Python?
Can someone assist? Thanks.

Answer Source

In Ruby, methods can be called without including empty parentheses after the method name, like so:

def func1
  puts "Hello!"

func1 # Calls func1 and prints "Hello!"

Because of this, when you write benchmark(func1, index1, array1), you're actually calling func1 with no arguments and passing the result to benchmark, not passing func1 to the benchmark function as you expected. In order to pass func1 as an object, you may obtain a wrapper object for the function using the method method, like this:

def func1
  puts "Hello!"

m = method(:func1) # Returns a Method object for func1, param2)

Most of the time though, that's not something you really want to do. Ruby supports a construct called blocks which is much better suited for this purpose. You may already be familiar with blocks from the each iterator Ruby uses for looping through arrays. Here's what it would look like to use blocks for your use case:

def benchmark
  start =
  yield - start # Returns time taken to perform func

# Or alternately:
# def benchmark(&block)
#   start =
# - start # Returns time taken to perform func
# end

def func1(index, array)
    # Perform computations based on index and array

def func2(index, array)
    # More computations....

benchmark { func1(index1, array1) }
benchmark { func1(index1, array2) }

In fact, Ruby has a standard library for benchmarking called Benchmark which uses blocks and probably already does exactly what you want.


require 'benchmark'

n = 5000000 do |x| { for i in 1..n; a = "1"; end } { n.times do   ; a = "1"; end } { 1.upto(n) do ; a = "1"; end }

The result:

    user     system      total        real
1.010000   0.000000   1.010000 (  1.014479)
1.000000   0.000000   1.000000 (  0.998261)
0.980000   0.000000   0.980000 (  0.981335)
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download