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

Ruby有一个内置的loop命令,可以永久地执行它后面的块(或直到中断为止)。 但是,当它与function上相似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修订版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命令在其工作中比通用目的更差

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

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

例如:

 loop do a = 2 break end puts a 

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

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

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

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

while循环有条件检查每个循环的顶部,而对比loop do...end没有条件不。 所以即使条件为真,计算的逻辑也越少,它仍然至少要进行一次检查。