In Ruby, methods can be called without including empty parentheses after the method name, like so:
def func1
puts "Hello!"
end
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!"
end
m = method(:func1) # Returns a Method object for func1
m.call(param1, 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 = Time.now
yield
Time.now - start # Returns time taken to perform func
end
# Or alternately:
# def benchmark(&block)
# start = Time.now
# block.call
# Time.now - start # Returns time taken to perform func
# end
def func1(index, array)
# Perform computations based on index and array
end
def func2(index, array)
# More computations....
end
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.
Usage:
require 'benchmark'
n = 5000000
Benchmark.bm do |x|
x.report { for i in 1..n; a = "1"; end }
x.report { n.times do ; a = "1"; end }
x.report { 1.upto(n) do ; a = "1"; end }
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)