代码之家  ›  专栏  ›  技术社区  ›  ddavison

为什么CoffeeScript比Ruby脚本快?

  •  1
  • ddavison  · 技术社区  · 12 年前

    我正在解决一个问题,这个问题要求我找出4000000以下所有偶数fibonacci数的和,我注意到下面的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
    

    花了将近 6-8秒 Ruby脚本找到4000000以下的所有偶数fibonacci数 0.2秒 以完成咖啡脚本转换的NodeJS执行。这是为什么??

    $ ruby --version
      ruby 2.1.0p0 (2013-12-25 revision 44422) [x86_64-darwin12.0]
    $ node --version
      v0.10.25
    
    1 回复  |  直到 12 年前
        1
  •  4
  •   Community Mohan Dere    9 年前

    让我们使用 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的“暖化”执行速度可能要快得多。

    推荐文章