Ruby 方法的测量和基准时间
Posted
技术标签:
【中文标题】Ruby 方法的测量和基准时间【英文标题】:Measure and Benchmark Time for Ruby Methods 【发布时间】: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年后,我认为这里有一些可靠的答案。谢谢。
【参考方案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
已保留。
【讨论】:
只是一个小修正。end
是保留的,所以使用其他变量名。
Time.now
会受到系统时钟调整的影响,因此最好改用Process.clock_gettime(Process::CLOCK_MONOTONIC)
。但是对于粗略的计算,这并不重要。 blog.dnsimple.com/2018/03/elapsed-time-with-ruby-the-right-way【参考方案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 的回答中弄清楚并不意味着它无效。以上是关于Ruby 方法的测量和基准时间的主要内容,如果未能解决你的问题,请参考以下文章