I like the way you've constructed your time
method. I have no suggestions for improvement, but I will say a few words about a related problem. Suppose you wished to measure the amount of time spent executing methods. Sometimes you might be able to write something simple such as:
require 'time'
t = Time.now
rv = my_method(*args)
et = t.Time.now - t
Other times that's not convenient. Suppose, for example, you were constructing an array whose elements were the return values of my_method
or my_method
returned an enumerator so that it could be chained to other methods.
As an example, let's suppose you wanted to sum the values of an array until a zero is encountered. One way to do that is to construct an enumerator stop_at_zero
that generates values from its receiver until it encounters a zero, then stops (i.e., raises a StopIteration
exception). We could then write:
arr.stop_at_zero.reduce(:+)
If we want to know how much time is spent executing stop_at_zero
we could construct it as follows.
class Array
def stop_at_zero
extime = Time.now
Enumerator.new do |y|
begin
each do |n|
sleep(0.5)
return y if n.zero?
y << n
end
ensure
$timings << [__method__, Time.now - extime]
end
end
end
end
I used a begin
, ensure
, end
block to make sure $timings << [__method__, Time.now - extime]
is executed when the method returns prematurely. sleep(0.5)
is of course just for illustrative purposes.
Let's try it.
$timings = []
arr = [1,7,0,3,4]
arr.stop_at_zero.reduce(:+)
#=> 8
$timings
#=> [[:stop_at_zero, 1.505672]]
$timings
will contain a history of execution times of all methods that contain the timing code.