When all you've got is a hammer, everything looks like a nail. So it can be said of the Array#each
method in Ruby, before discovering the utility, elegance, and syntactic pleasure of Array#map
and Array#select
and other iterable methods. What I'm curious of is:
Why is there an actual increase in performance when using a more precise iterable method? Is this true in general?
For example, in
require 'benchmark'
array = (1..100000).to_a
puts Benchmark.measure {
100.times do
array.map { |el| el.even? }
end
}
puts Benchmark.measure {
100.times do
new_array = []
array.each do |el|
new_array << el.even?
end
end
}
# ruby bench.rb
# 0.450598 0.015524 0.466122 ( 0.466802)
# 0.496796 0.018525 0.515321 ( 0.516196)
Benchmark
always shows a temporal performance difference in favor of Array#map
. In the following code:
puts Benchmark.measure {
100.times do
array.select { |el| el.even? }
end
}
puts Benchmark.measure {
100.times do
new_array = []
array.each do |el|
if el.even?
new_array << el
end
end
end
}
# ruby bench.rb
# 0.405254 0.007965 0.413219 ( 0.413733)
# 0.471416 0.008875 0.480291 ( 0.481079)
Array#select
beats a jerry-rigged Array#each
every time.
So why do these more precise methods produce notably better performance? And is this a general axiom in Ruby and/or all languages?