测量和基准时间的Ruby方法


87

如何在Ruby中测量方法和该方法中的各个语句所花费的时间。如果您看到以下方法,我想测量该方法花费的总时间以及数据库访问和Redis访问所花费的时间。我不想在每条语句之前写Benchmark.measure。红宝石解释器是否为我们提供了任何帮助?

def foo
# code to access database
# code to access redis. 
end

有一些类似于new Date()ruby的javascript的东西,但是我不记得正确的语法。应该会给您一个不错的Google列表
里根2012年

1
@Phani您能选择一个正确的答案吗?8年后,我认为这里有一些可靠的答案。谢谢。
约书亚品特

Answers:


112

您可以使用该Time对象。(时间文件

例如,

start = Time.now
# code to time
finish = Time.now

diff = finish - start

diff 将以秒为单位,作为浮点数。

编辑:end保留。


13
只是一个小的更正。end是保留的,因此请使用其他一些变量名。
詹森·金

4
Time.now受系统时钟调整的影响,因此最好使用它Process.clock_gettime(Process::CLOCK_MONOTONIC)。但是对于粗略的计算这并不重要。blog.dnsimple.com/2018/03/
经过时间与

102

最简单的方法:

require 'benchmark'

def foo
 time = Benchmark.measure {
  code to test
 }
 puts time.real #or save it to logs
end

样本输出:

2.2.3 :001 > foo
  5.230000   0.020000   5.250000 (  5.274806)

值包括:CPU时间,系统时间,总和实际经过时间。

资料来源:ruby docs


40
Benchmark.realtime { block }如果您只想实时显示,也可以做
jmccure 2015年

35

使用Benchmark的报告

require 'benchmark' # Might be necessary.

def foo
  Benchmark.bm( 20 ) do |bm|  # The 20 is the width of the first column in the output.
    bm.report( "Access Database:" ) do 
      # Code to access database.
    end
   
    bm.report( "Access Redis:" ) do
      # Code to access redis.
    end
  end
end

这将输出如下内容:

                        user     system      total        real
Access Database:    0.020000   0.000000   0.020000 (  0.475375)
Access Redis:       0.000000   0.000000   0.000000 (  0.000037)

<------ 20 -------> # This is where the 20 comes in. NOTE: This is not shown in output.

这里可以找到更多信息。


2
我只是回到自己的答案,并且再次对Benchmark的处理方式印象深刻。爱露比。
Joshua Pinter

2
这应该是首选答案:因为从Ruby 2.2开始,Benchmark该类使用单调时钟,如其他答案所述。例如,参见下面的源代码,并在第286行中查找“ def measure”: github.com/ruby/ruby/blob/ruby_2_2/lib/benchmark.rb
Purplejacket

17

许多答案建议使用Time.now。但是值得一提的是,它Time.now可以改变。系统时钟可能会漂移,并且可能会被系统管理员或NTP纠正。因此,Time.now可能会向前或向后跳转,并为基准测试提供不准确的结果。

更好的解决方案是使用操作系统的单调时钟,该时钟一直在向前发展。Ruby 2.1及更高版本允许通过以下方式对此进行访问:

start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
# code to time
finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
diff = finish - start # gets time is seconds as a float

您可以在此处阅读更多详细信息。您还可以看到流行的Ruby项目Sidekiq转换为单调时钟


7

再想一想,使用Ruby代码块参数定义measure()函数可以帮助简化时间度量代码:

def measure(&block)
  start = Time.now
  block.call
  Time.now - start
end

# t1 and t2 is the executing time for the code blocks.
t1 = measure { sleep(1) }

t2 = measure do
  sleep(2)
end

在您的定义中,您称之为benchmark。使用时称为measure。请解决此问题。
桑德罗L

4

本着wquist的回答的精神,但更简单一点,您也可以像下面这样进行操作:

start = Time.now
# code to time
Time.now - start

这个答案是(略)不同的回答问题的方式。仅仅因为您可以从@wquist的答案中找出答案,并不意味着它无效。
thesecretmaster

3

查看ruby-prof包装,它应该有您所需要的。它将创建带有定时的巨大调用堆栈。

http://ruby-prof.rubyforge.org/

它可能过于精细,在这种情况下,仅将较大的部分包裹起来Benchmark.measure可能是一个好方法。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.