这很丑陋:
t = Time.now
result = do_something
elapsed = Time.now - t
我试过了:
elapsed = time do
result = do_something
end
def time
t = Time.now
yield
Time.now - t
end
这样更好。但问题是在块结束后result
超出了范围。
那么,有更好的计时方法吗?或者使用result
?
答案 0 :(得分:4)
一种非常惯用的方法是使用标准库。 :)
require 'benchmark'
result = nil
elapsed = Benchmark.realtime do
result = do_something
end
答案 1 :(得分:2)
你在这里有正确的想法,但要避免范围问题,请执行以下操作:
result = nil
elapsed = time do
result = do_something
end
答案 2 :(得分:2)
我喜欢你构建time
方法的方式。我没有改进的建议,但我会就相关问题说几句话。假设您希望测量执行方法所花费的时间。有时您可能会写一些简单的内容,例如:
require 'time'
t = Time.now
rv = my_method(*args)
et = t.Time.now - t
其他时候不方便。例如,假设您构造的数组的元素是my_method
或my_method
的返回值,则返回一个枚举器,以便它可以链接到其他方法。
作为一个例子,假设您想要对数组的值求和,直到遇到零。一种方法是构造一个枚举器stop_at_zero
,它从接收器生成值,直到遇到零,然后停止(即引发StopIteration
异常)。然后我们可以写:
arr.stop_at_zero.reduce(:+)
如果我们想知道执行stop_at_zero
花费了多少时间,我们可以按如下方式构建它。
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
我使用begin
,ensure
,end
块来确保在方法过早返回时执行$timings << [__method__, Time.now - extime]
。 sleep(0.5)
当然只是为了说明目的。
试试吧。
$timings = []
arr = [1,7,0,3,4]
arr.stop_at_zero.reduce(:+)
#=> 8
$timings
#=> [[:stop_at_zero, 1.505672]]
$timings
将包含包含计时代码的所有方法的执行时间历史记录。