【发布时间】: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; end,StopIteration在枚举器生成其最后一个值后执行next时引发。可以想象,相关的开销可能是基准测试结果的原因,但我预计使用while(true)或while(1)(FORTRAN 遗物)所节省的时间通常与在循环中执行语句所花费的时间相比相形见绌。为了保持一致性,我总是使用loop。
标签: ruby performance while-loop infinite-loop