Ruby has a built-in loop command that executes the block following it forever (or until stopped by break). However, when comparing it against the functionally similar while true, it is significantly slower:
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
Under Ruby 2.4.1 (p111 (2017-03-22 revision 58053) [x64-mingw32]), the difference is striking:
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
Why is there such a performance difference? And why is the single-purpose loop command worse at its job than the general-purpose while?
(Benchmark copied from here, licensed under CC-BY-SA)
loop is a kernel method which takes a block.  As a reminder, a block
introduces new local variable scope.
For example:
loop do
 a = 2
 break
end
puts a
Will return an error such as: "NameError: undefined local variable or method `a' for main:Object" On the other hand:
while true
 a = 2
 break
end
p a #=> return a = 2
So I wouldn't be surprised that loop creates some sort of local variable(s) such as one for the break statement that is (are) going to be in its scope. Creating/deleting those variables at every iteration slow down the process.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With