【问题标题】:High performance way to get current time in Ruby MRI在 Ruby MRI 中获取当前时间的高性能方法
【发布时间】:2013-10-20 22:16:03
【问题描述】:

我正在优化对性能敏感的 TTL 缓存。分析器说,大约 25% 的时间花在 Time.nowTime#to_f 上,它们用于计算生存时间。

有没有一种可靠的方法可以在 Ruby MRI 中以简单的数字形式(任何粒度)而不是花哨的 Time 对象来获取当前时间?

【问题讨论】:

  • 快速浏览一下time.c 表明,如果你只是在做Time.now.to_fTime 是相当薄的。也许尝试编写自己的 C 扩展,它只是从系统调用中获取时间值并将其转换为 Ruby 数字。
  • 您是在自己分析缓存失效系统吗?您是否有针对该特定组件的基准目标?您可能将精力集中在错误的组件上。带有浮点比较的 Time.now 应该能够评估每秒数万个缓存 TTL 是否失效。

标签: ruby-on-rails ruby performance time profiling


【解决方案1】:

TL;DR

您的问题并不清楚您真正需要什么样的性能,或者为什么您的代码无法提供这种性能水平。对于大多数用例,MRI 的性能相当不错。如果您有一个特殊的用例,并且以下建议都不适合您,那么您可能需要重新审视代码中的假设,或者确定 Ruby 解释器是否真的是需要微秒级性能的工作的正确工具,或者纳秒范围。

基准测试时间

Ruby 通常不具备最快的代码执行速度,但通常“足够快”。在我的系统上,MRI 平均在大约 2 毫秒内返回 1,000 个Time 对象。例如,MRI 报告:

require 'benchmark'
Benchmark.measure do 1_000.times { t = Time.now.to_f } end
=> #<Benchmark::Tms:0x00000000be2f30
 @cstime=0.0,
 @cutime=0.0,
 @label="",
 @real=0.001831756,
 @stime=0.0,
 @total=0.0,
 @utime=0.0>

需要考虑的一些选项

我始终得到大约200.times 的微秒范围内的基准测试时间。这表明一些值得考虑的事情:

  1. 减少投票次数可能会有所帮助。
  2. 使用套接字或管道将数据从某个更快的进程馈送到 Ruby 中可能是一种有用的方法。
  3. 您可能希望 Ruby 生成一个以 C 速度运行的后台进程。
  4. 您始终可以编写自己的原生扩展。

换句话说,您也许可以重新考虑您的问题,以便 Ruby 部分对时间不那么敏感。 Ruby 有很多特性使它能够与其他进程和应用程序通信,使用进程间通信可以帮助您异步执行必要的操作。

【讨论】:

  • 是的,我切换到每 N 次操作到期,时间性能问题就消失了。
【解决方案2】:

假设您使用的是 Unixish 系统(Linux 或 OSX),您可以执行以下操作:

time = `date +%s`.squish.to_i

【讨论】:

  • 这通常比原生 Ruby 慢,因为它每次循环都需要执行一个进程。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-25
  • 2013-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多