2016-09-22 71 views
4

这是很丑陋:在Ruby中测量时间的惯用方法是什么?

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的好方法?

回答

4

一个真正惯用的方法是使用标准库。 :)

require 'benchmark' 

result = nil 
elapsed = Benchmark.realtime do 
    result = do_something 
end 
2

你有正确的想法在这里,但要避免的范围问题,做到这一点:

result = nil 
elapsed = time do 
    result = do_something 
end 
2

我喜欢你已经构建了您的time方法的方式。我没有任何改进建议,但我会对相关问题说几句话。假设你想测量执行方法的时间量。有时候你可能会写些简单的东西,比如:

require 'time' 

t = Time.now 
rv = my_method(*args) 
et = t.Time.now - t 

其他时候这样不方便。例如,假设你正在构造一个数组,其元素是my_methodmy_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 

我使用的beginensureend块以确保$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将包含的含有时刻码所有方法的执行时间的历史。

相关问题