【问题标题】:#inject and slowness#注入和缓慢
【发布时间】:2008-11-25 21:03:55
【问题描述】:

我经常听到 Ruby 的注入方法被批评为“慢”。由于我更喜欢​​这个函数,并看到其他语言的等价物,我很好奇它是否仅仅是 Ruby 的 实现 缓慢的方法,或者它本质上是一种缓慢的做事方式(例如应该对于非小型收藏品应避免)?

【问题讨论】:

    标签: ruby functional-programming performance methods


    【解决方案1】:

    inject 类似于fold,并且在其他语言中非常有效,特别是fold_left,因为它是尾递归的。

    【讨论】:

      【解决方案2】:

      这主要是一个实现问题,但这让您对比较有一个很好的了解:

      $ ruby -v
      ruby 1.8.7 (2008-08-11 patchlevel 72) [i486-linux]
      $ ruby exp/each_v_inject.rb 
      Rehearsal -----------------------------------------------------
      loop                0.000000   0.000000   0.000000 (  0.000178)
      fixnums each        0.790000   0.280000   1.070000 (  1.078589)
      fixnums each add    1.010000   0.290000   1.300000 (  1.297733)
      Enumerable#inject   1.900000   0.430000   2.330000 (  2.330083)
      -------------------------------------------- total: 4.700000sec
      
                              user     system      total        real
      loop                0.000000   0.000000   0.000000 (  0.000178)
      fixnums each        0.760000   0.300000   1.060000 (  1.079252)
      fixnums each add    1.030000   0.280000   1.310000 (  1.305888)
      Enumerable#inject   1.850000   0.490000   2.340000 (  2.340341)
      

      exp/each_v_inject.rb

      require 'benchmark'
      
      total = (ENV['TOTAL'] || 1_000).to_i
      fixnums = Array.new(total) {|x| x}
      
      Benchmark.bmbm do |x|
        x.report("loop") do
          total.times { }
        end
      
        x.report("fixnums each") do
          total.times do |i|
            fixnums.each {|x| x}
          end
        end
      
        x.report("fixnums each add") do
          total.times do |i|
            v = 0
            fixnums.each {|x| v += x}
          end
        end    
      
        x.report("Enumerable#inject") do
          total.times do |i|
            fixnums.inject(0) {|a,x| a + x }
          end
        end  
      end
      

      所以是的,它很慢,但随着实施的改进,它应该成为一个非问题。它所做的事情并没有什么固有的要求它变慢。

      【讨论】:

        【解决方案3】:

        each_with_object 可能比inject 更快,如果您要改变现有对象而不是在每个块中创建新对象。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-10-29
          • 2013-04-04
          • 1970-01-01
          • 1970-01-01
          • 2017-08-04
          • 1970-01-01
          • 2012-03-12
          • 1970-01-01
          相关资源
          最近更新 更多