#inject and slowness

I've often heard the Ruby injection method criticized as "slow". Since I love this feature and I see equivalents in other languages, I am curious if this is just a slow way of doing Ruby, or if this is inherently a slow way of doing things (eg should be avoided for non-small sets)?

+1


source to share


3 answers


inject

is similar to fold

and can be very efficient in other languages, fold_left

in particular since it is tail-recursive.



+3


source


This is mostly an implementation issue, but it gives you a good idea of ​​the comparison:

$ 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

      

So, yes, it's slow, but as improvements happen in the implementation, it should become a non-problem. As far as what it does, there is nothing that requires it to be slower.

+2


source


each_with_object

may be faster than inject

if you mutate an existing object rather than creating a new object in every block.

0


source







All Articles