【问题标题】:Measure and Benchmark Time for Ruby MethodsRuby 方法的测量和基准时间
【发布时间】:2012-07-09 12:31:39
【问题描述】:

如何在 Ruby 中测量一个方法和该方法中的各个语句所花费的时间。如果您看到下面的方法,我想测量该方法所花费的总时间以及数据库访问和 redis 访问所花费的时间。我不想在每个陈述之前都写 Benchmark.measure。 ruby 解释器是否为我们提供了执行此操作的任何钩子?

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

【问题讨论】:

  • 有一些类似于 ruby​​ 的 new Date() 的东西,但我不记得正确的语法。不过应该给你一个不错的谷歌列表
  • @Phani 你能选择一个正确的答案吗? 8年后,我认为这里有一些可靠的答案。谢谢。

标签: ruby-on-rails ruby time benchmarking interpreter


【解决方案1】:

最简单的方法:

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

【讨论】:

  • 如果你只是想要实时,你也可以Benchmark.realtime { block }
【解决方案2】:

您可以使用Time 对象。 (Time Docs)

例如,

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

diff = finish - start

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

编辑:end 已保留。

【讨论】:

【解决方案3】:

使用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.

更多信息可以在here找到。

【讨论】:

  • 我刚刚回到自己的答案,并(再次)对 Benchmark 处理此问题的方式印象深刻。爱红宝石。
  • 这应该是首选答案:因为从 Ruby 2.2 开始,Benchmark 类使用单调时钟,如其他答案中所述。例如,请参阅以下源代码,并在第 286 行查找“def measure”:github.com/ruby/ruby/blob/ruby_2_2/lib/benchmark.rb
【解决方案4】:

许多答案建议使用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

您可以阅读更多详细信息here。您还可以看到流行的 Ruby 项目 Sidekiq 已切换到 monotonic clock

【讨论】:

  • 提供秒以外的其他单位(ms、µs、ns、...),请参阅core doc
【解决方案5】:

再想一想,使用 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。请解决这个问题。
【解决方案6】:

本着wquist's answer的精神,但更简单一点,你也可以像下面这样:

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

【讨论】:

  • 这个答案是一种(稍微)不同的回答问题的方式。仅仅因为您可以从@wquist 的回答中弄清楚并不意味着它无效。
猜你喜欢
  • 2015-01-07
  • 2023-04-07
  • 1970-01-01
  • 1970-01-01
  • 2022-09-26
  • 2015-09-14
  • 2022-01-23
  • 2020-01-22
  • 1970-01-01
相关资源
最近更新 更多