如何在 Ruby 中以毫秒为单位计算操作的时间?

我希望计算出一个特定函数使用了多少毫秒。所以我到处找,但是找不到在 Ruby 中以毫秒精度获得时间的方法。

你如何做到这一点? 在大多数编程语言中,它只是像什么

start = now.milliseconds
myfunction()
end = now.milliseconds
time = end - start
66462 次浏览

使用 Time.now. to _ f

您应该查看基准测试模块以执行基准测试。然而,作为一种快速而粗糙的计时方法,你可以使用这样的东西:

def time
now = Time.now.to_f
yield
endd = Time.now.to_f
endd - now
end

注意 Time.now.to_f的使用,与 to _ i 不同,它不会截断到秒。

你可以使用 Ruby 的 Time类,例如:

t1 = Time.now
# processing...
t2 = Time.now
delta = t2 - t1 # in seconds

现在,delta是一个 float对象,您可以得到类提供的尽可能细的结果。

你也可以使用内置的 Benchmark.scale 函数:

require "benchmark"
puts(Benchmark.measure { sleep 0.5 })

印刷品:

0.000000   0.000000   0.000000 (  0.501134)

absolute_time gem 是 Benchmark 的替代品,但是使用本机指令要准确得多。

使用 Time.now.to_i返回从1970/01/01过去的第二个

date1 = Time.now.to_f
date2 = Time.now.to_f
diff = date2 - date1

有了这个,你将有差异 第二名大小。如果你想它在 毫秒,只是添加到代码

diff = diff * 1000

如果你用

date = Time.now.to_i

您以秒为单位获取时间,这远远不够准确,特别是如果您对小块代码计时的话。

我有一个 gem,它可以配置你的 Ruby 方法(实例或类)-https://github.com/igorkasyanchuk/benchmark_methods

不再有这样的代码:

t = Time.now
user.calculate_report
puts Time.now - t

现在你可以做:

benchmark :calculate_report # in class

调用你的方法

user.calculate_report

使用 Time.now(返回挂钟时间)作为基线有两个问题,可能导致意外行为。这是由于墙钟时间受到诸如插入闰秒或 时间旋转等变化的影响,以便将本地时间调整为参考时间。

如果在测量过程中插入了闰秒,那么它会偏离一秒。类似地,根据当地系统条件,您可能不得不处理夏令时、运行速度更快或更慢的时钟,或者时钟甚至跳回到过去,导致负持续时间,以及许多其他问题。

解决这个问题的方法是使用不同的时钟: 单调的时钟。这种类型的时钟与挂钟有不同的属性。 它以监控的方式增加,也就是说永远不会回到过去,并以恒定的速率增加。这样,它就不再代表墙上的时钟(也就是你从墙上的时钟上读到的时间) ,而是一个时间戳,你可以将它与后来的时间戳进行比较,得到不同的结果。

在 Ruby 中,可以在 Process.clock_gettime(Process::CLOCK_MONOTONIC)中使用这样的时间戳,如下所示:

t1 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
# => 63988.576809828


sleep 1.5 # do some work


t2 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
# => 63990.08359163


delta = t2 - t1
# => 1.5067818019961123
delta_in_milliseconds = delta * 1000
# => 1506.7818019961123

Process.clock_gettime方法将时间戳作为浮点数返回,浮点数为小数秒。返回的实际数字没有定义的含义(您应该依赖这个含义)。但是,您可以确保下一个调用将返回更大的数字,并且通过比较这些值,您可以得到实时差异。

这些属性使得该方法成为测量时间差异的主要候选方法,而无需看到您的程序在最不合适的时间失败(例如,在新年前夜的午夜时分,插入了另一个闰秒)。

这里使用的 Process::CLOCK_MONOTONIC常量可用于所有现代 Linux、 BSD 和 macOS 系统以及用于 Windows 的 Linux 子系统。然而,它还不适用于“原始”的 Windows 系统。在这里,您可以使用 GetTickCount64系统调用而不是 Process.clock_gettime,后者在 Windows 上也返回毫秒粒度的计时器值(> = Windows Vista,Windows Server 2008)。

对于 Ruby,您可以这样调用这个函数:

require 'fiddle'


# Get a reference to the function once
GetTickCount64 = Fiddle::Function.new(
Fiddle.dlopen('kernel32.dll')['GetTickCount64'],
[],
-Fiddle::TYPE_LONG_LONG # unsigned long long
)


timestamp = GetTickCount64.call / 1000.0
# => 63988.576809828

我们还可以创建一个简单的函数来记录任何代码块:

def log_time
start_at = Time.now


yield if block_given?


execution_time = (Time.now - start_at).round(2)
puts "Execution time: #{execution_time}s"
end


log_time { sleep(2.545) } # Execution time: 2.55s