我正在解决一个问题,要求我找到所有偶数斐波那契数字在4,000,000以下的总和,我注意到下面的CoffeeScript执行速度比下面的Ruby快。
sum = 0
f = (n) ->
if n == 0 then return 0
else if n == 1 then return 1
else return f(n-1) + f(n-2)
console.log "Starting..."
for i in [1..4000000]
ff = f(i)
break if ff >= 4000000
sum += ff if ff % 2 == 0
console.log ".." + ff
console.log "Sum:" + sum
sum = 0
def F(n)
if n.eql? 0
return 0
elsif n.eql? 1
return 1
else
return F(n-1) + F(n-2)
end
end
puts "Starting..."
4000000.times do |num|
the_num = F(num)
break if the_num >= 4000000
sum += the_num if the_num % 2 == 0
puts ".." + the_num.to_s
end
puts "Sum:" + sum.to_s
Ruby脚本花了将近 6-8秒来查找所有甚至斐波纳契数字都在4,000,000以下,而大约 0.2秒完成NodeJS执行咖啡因的翻译。这是为什么?
$ ruby --version
ruby 2.1.0p0 (2013-12-25 revision 44422) [x86_64-darwin12.0]
$ node --version
v0.10.25
答案 0 :(得分:4)
让我们使用ruby-prof:
对其进行分析# so_21908065.rb
sum = 0
def F(n)
# using == instead of eql? speeds up from ~ 7s to ~ 2s
if n == 0
return 0
elsif n == 1
return 1
else
return F(n-1) + F(n-2)
end
end
puts "Starting..."
1.upto(4000000) do |num|
the_num = F(num)
break if the_num >= 4000000
sum += the_num if the_num % 2 == 0
puts ".." + the_num.to_s
end
puts "Sum:" + sum.to_s
$ ruby-prof so_21908065.rb
%self total self wait child calls name
16.61 27.102 27.102 0.000 0.000 87403761 Fixnum#==
9.57 15.615 15.615 0.000 0.000 48315562 Fixnum#-
4.92 8.031 8.031 0.000 0.000 24157792 Fixnum#+
0.00 0.000 0.000 0.000 0.000 70 IO#write
0.00 163.123 0.000 0.000 163.123 1 Integer#upto
0.00 163.122 0.000 0.000 163.122 48315596 *Object#F
0.00 0.000 0.000 0.000 0.000 35 IO#puts
0.00 0.000 0.000 0.000 0.000 34 Fixnum#to_s
0.00 0.001 0.000 0.000 0.000 35 Kernel#puts
0.00 0.000 0.000 0.000 0.000 34 String#+
0.00 163.123 0.000 0.000 163.123 2 Global#[No method]
0.00 0.000 0.000 0.000 0.000 34 Fixnum#>=
0.00 0.000 0.000 0.000 0.000 2 IO#set_encoding
0.00 0.000 0.000 0.000 0.000 33 Fixnum#%
0.00 0.000 0.000 0.000 0.000 1 Module#method_added
* indicates recursively called methods
所以主要罪魁祸首是Fixnum#==
,Fixnum#-
和Fixnum#+
。
正如@HolgerJust所指出的那样,由于JIT优化,可能会使一个“温暖”的JRuby执行速度更快。