1

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

4

3 回答 3

3

inject就像fold, 并且在其他语言中可能非常有效,fold_left特别是因为它是尾递归的。

于 2008-11-25T21:13:08.017 回答
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

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

于 2008-11-26T21:43:29.437 回答
0

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

于 2011-06-18T13:55:50.180 回答