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获得许可)
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 没有条件。因此,即使该条件为真,它计算的逻辑也较少,它仍然至少会多做一项检查。