【发布时间】:2008-11-25 21:03:55
【问题描述】:
我经常听到 Ruby 的注入方法被批评为“慢”。由于我更喜欢这个函数,并看到其他语言的等价物,我很好奇它是否仅仅是 Ruby 的 实现 缓慢的方法,或者它本质上是一种缓慢的做事方式(例如应该对于非小型收藏品应避免)?
【问题讨论】:
标签: ruby functional-programming performance methods
我经常听到 Ruby 的注入方法被批评为“慢”。由于我更喜欢这个函数,并看到其他语言的等价物,我很好奇它是否仅仅是 Ruby 的 实现 缓慢的方法,或者它本质上是一种缓慢的做事方式(例如应该对于非小型收藏品应避免)?
【问题讨论】:
标签: ruby functional-programming performance methods
inject 类似于fold,并且在其他语言中非常有效,特别是fold_left,因为它是尾递归的。
【讨论】:
这主要是一个实现问题,但这让您对比较有一个很好的了解:
$ 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
所以是的,它很慢,但随着实施的改进,它应该成为一个非问题。它所做的事情并没有什么固有的要求它变慢。
【讨论】:
each_with_object 可能比inject 更快,如果您要改变现有对象而不是在每个块中创建新对象。
【讨论】: