【问题标题】:Why is Ruby's loop command slower than while true?为什么 Ruby 的循环命令比 while true 慢?
【发布时间】:2017-12-17 14:16:03
【问题描述】:

Ruby 有一个内置的loop 命令,它永远执行它后面的块(或直到被break 停止)。但是,当将其与功能相似的 while true 进行比较时,它的速度要慢得多:

require "benchmark/ips"

NUMBER = 100_000_000

def fast
  index = 0
  while true
    break if index > NUMBER
    index += 1
  end
end

def slow
  index = 0
  loop do
    break if index > NUMBER
    index += 1
  end
end

Benchmark.ips do |x|
  x.report("While Loop")  { fast }
  x.report("Kernel loop") { slow }
  x.compare!
end

在 Ruby 2.4.1 (p111 (2017-03-22 revision 58053) [x64-mingw32]) 下,差异是惊人的:

Warming up --------------------------------------
          While Loop     1.000  i/100ms
         Kernel loop     1.000  i/100ms
Calculating -------------------------------------
          While Loop      0.630  (± 0.0%) i/s -      4.000  in   6.350897s
         Kernel loop      0.190  (± 0.0%) i/s -      1.000  in   5.274249s

Comparison:
          While Loop:        0.6 i/s
         Kernel loop:        0.2 i/s - 3.32x  slower

为什么会有这样的性能差异?为什么单一用途的loop 命令比通用的while 更糟糕

(从 here 复制的基准,根据 CC-BY-SA 许可)

【问题讨论】:

  • begin i+=1 end while i<=NUMBER 更快。去图...
  • Kernel#loop 拯救StopIteration 异常。它的反应是跳出循环。如果enum = [1,2,3].to_enum; loop do; enum.next; endStopIteration 在枚举器生成其最后一个值后执行next 时引发。可以想象,相关的开销可能是基准测试结果的原因,但我预计使用while(true)while(1)(FORTRAN 遗物)所节省的时间通常与在循环中执行语句所花费的时间相比相形见绌。为了保持一致性,我总是使用loop

标签: ruby performance while-loop infinite-loop


【解决方案1】:

通常,要从基准测试中获得更准确的结果,您可以增加执行测试的次数并在多个基准测试中平均结果。

while 循环在每个循环的顶部都有一个检查条件,相比之下,loop do...end 没有条件不检查。因此,即使该条件为真,它计算的逻辑也更少,它仍然至少多做一次检查。

【讨论】:

  • 这似乎没有回答这个问题。 while 循环被呈现为更快的选项,尽管有条件...
  • 寻找答案的最佳位置是源代码。因此,可以比较正在运行的内容,而不仅仅是基准所能提供的内容。
  • 也许你应该在下一次发布错误的猜测作为答案之前这样做......
【解决方案2】:

loop 是一个采用block 的内核方法。提醒一下,block 引入新的局部变量作用域

例如:

loop do
 a = 2
 break
end
puts a

将返回错误,例如:“NameError: undefined local variable or method `a' for main:Object” 另一方面:

while true
 a = 2
 break
end
p a #=> return a = 2

因此,loop 创建了某种局部变量,例如用于将在其范围内的 break 语句的局部变量,我不会感到惊讶。在每次迭代中创建/删除这些变量会减慢过程。

【讨论】:

  • 对循环的快速评论 1. 将条件放在末尾通常更好 2. 扩展条件似乎可以提高(两个循环的)性能,所以编写以下代码 f index > NUMBER break end You可以在这里获取更多信息launchschool.com/books/ruby/read/loops_iterators
猜你喜欢
  • 2021-04-02
  • 1970-01-01
  • 2012-11-25
  • 1970-01-01
  • 2014-02-17
  • 2017-11-09
  • 2015-10-07
  • 1970-01-01
  • 2013-03-06
相关资源
最近更新 更多