Is `map` faster than `each`?
I think yes.
I've tried this test
require "benchmark"
n=10000
arr=Array.new(10000,1)
Benchmark.bm do |x|
#Map
x.report do
n.times do
result = arr.map {|a| a + 2}
end
end
#Each
x.report do
n.times do
result = []
arr.each do |a|
result.push(a + 2)
end
end
end
end
And I got this times
user system total real
5.790000 0.060000 5.850000 ( 5.846956)
8.210000 0.030000 8.240000 ( 8.233849)
Seems like map it's faster
I saw this video http://confreaks.tv/videos/goruco2015-how-to-performance she shows many ruby profiles and tools, if you are interested to improve your performance you will find a lot of tips there.
added
This is a crazy behavior for me!
require "benchmark"
n=10000
arr=Array.new(10000,1)
Benchmark.bm do |x|
#Map
x.report do
n.times do
result = arr.map {|a| a + 2}
end
end
#Each and push
x.report do
n.times do
result = []
arr.each do |a|
result.push(a + 2)
end
end
end
#Each and <<
x.report do
n.times do
result = []
arr.each do |a|
result << (a + 2)
end
end
end
end
and the result
user system total real
5.880000 0.080000 5.960000 ( 5.949504)
8.160000 0.010000 8.170000 ( 8.164736)
6.630000 0.010000 6.640000 ( 6.632686)
is the operator "<<" faster than method push? I didn't expect that, I thought that was a kind of alias.
each
should be faster than map
since the former does not modify/create anything while the latter does. But in your code, you are comparing different things. It is push
that is taking time. Your code is irrelevant from comparing each
and map
.
This is the source for each
in MRI v2.2.2:
VALUE
rb_ary_each(VALUE array)
{
long i;
volatile VALUE ary = array;
RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
for (i=0; i<RARRAY_LEN(ary); i++) {
rb_yield(RARRAY_AREF(ary, i));
}
return ary;
}
and this is the source for map
:
static VALUE
rb_ary_collect(VALUE ary)
{
long i;
VALUE collect;
RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
collect = rb_ary_new2(RARRAY_LEN(ary));
for (i = 0; i < RARRAY_LEN(ary); i++) {
rb_ary_push(collect, rb_yield(RARRAY_AREF(ary, i)));
}
return collect;
}
Notice that map
and each
are almost the same (which is to be expected) but map
also needs to create an array, and then it does a push. Your version of each
in Ruby is basically doing the same thing, but yours is Ruby, this is C, so there will be extra overhead through recreating the lower level at the higher, and that C is faster than Ruby in general anyway.