在Ruby中测量时间的惯用方法是什么?

时间:2016-09-22 17:22:12

标签: ruby ruby-2.3

这很丑陋:

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

的好方法

3 个答案:

答案 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_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将包含包含计时代码的所有方法的执行时间历史记录。