I'd expect Ruby's parser would make this trivial optimization, however is seems it does not (speaking about YARV implementations, Ruby 1.9.x, 2.0.0):
require 'benchmark'
def fib1
a, b = 0, 1
while b < 9999**4000
a, b = b, a+b
end
puts "\tdone !"
end
MAX_FIB = 9999**4000
def fib2
a, b = 0, 1
while b < MAX_FIB
a, b = b, a+b
end
puts "\tdone !"
end
if __FILE__ == $0
Benchmark.bm do |r|
r.report('plain') { fib1 }
r.report('predefined constant') { fib2 }
end
end
plain done !
32.810000 0.220000 33.030000 ( 33.069854)
predefined constant done !
0.120000 0.000000 0.120000 ( 0.119303)
As both methods are identical except use of predefined constant instead of an constant expression in the second, it seems Ruby interpreter calculates power constant each loop again and again.
Is there some material why Ruby does not do this basic optimization at all or just in some specific cases ?
I am sorry for giving another answer, but I don't want to remove or edit my previous one because of the interesting discussion under it.
As Jörg W Mittag said, ruby has to calculate expression given to while
each time because it is simply impossible to say it is constant. For an extreme example, I come up with following code:
class Fixnum
alias :original_plus :+
@@increment = 0
def self.increase!
@@increment = @@increment.original_plus 1
end
def +(other)
(original_plus(other)).original_plus(@@increment)
end
end
while 1+1 < 5
puts Fixnum.increase!
end
puts 'done'
# 1
# 2
# 3
# done
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