为什么Ruby的循环命令比true更慢?

Man*_*ara 4 ruby performance infinite-loop while-loop

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
Run Code Online (Sandbox Code Playgroud)

在Ruby 2.4.1(p111(2017-03-22修订版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
Run Code Online (Sandbox Code Playgroud)

为什么会出现这样的性能差异?为什么单一目的loop命令在工作上比通用目的更糟while

(基准复制自此处,根据CC-BY-SA获得许可)

Ste*_*uet 6

loop是一个需要的内核方法block.作为提醒,block 引入了新的局部变量范围.

例如:

loop do
 a = 2
 break
end
puts a
Run Code Online (Sandbox Code Playgroud)

将返回错误,例如:" NameError:未定义的局部变量或方法`a'用于main:Object "另一方面:

while true
 a = 2
 break
end
p a #=> return a = 2
Run Code Online (Sandbox Code Playgroud)

所以我不会感到惊讶的是loop创建某种局部变量,例如一个用于break语句的局部变量,它将在其范围内.在每次迭代时创建/删除这些变量会减慢进程.


小智 -5

一般来说,为了从基准测试中获得更准确的结果,您可以增加测试次数,并对多个基准测试结果进行平均。

while循环在每个循环的顶部都有一个要检查的条件,相反则loop do...end 没有条件。因此,即使该条件为真,它计算的逻辑也较少,它仍然至少会多做一项检查。

  • 这似乎并不能回答问题。“while”循环被认为是更快的选项,尽管有条件...... (7认同)
  • 也许你应该这样做,下次,在发布错误的猜测作为答案之前...... (5认同)