2015-07-21 90 views
3

map在遍歷數組時比each更快?兩者之間有速度差異嗎?`map`比`each`更快嗎?

  • 地圖

    result = arr.map {|a| a + 2} 
    
  • 每個

    result = [] 
    arr.each do |a| 
        result.push(a + 2) 
    end 
    
+2

我認爲在這種情況下速度並不重要。任何加速都會以不太明確的代碼爲代價。 – Max

回答

5

我想是的。

我試過這個測試

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 

而且我得到了這個時代

 user  system  total  real 
    5.790000 0.060000 5.850000 ( 5.846956) 
    8.210000 0.030000 8.240000 ( 8.233849) 

好像地圖這

我看到這個視頻更快http://confreaks.tv/videos/goruco2015-how-to-performance 她表示許多紅寶石配置文件和工具,如果你有興趣提高你的表現,你會發現很多技巧。

添加

這對我來說是瘋狂的行爲!

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 

,結果

 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) 

是運營商 「< <」 比法推得更快?我沒有想到,我認爲這是一種別名。

+1

我跑了很多次,並改變順序(每個在開始,然後映射),並始終得到相同的值。 –

4

each應該比map更快,因爲前者不修改/,而後者則創造任何東西。但是在你的代碼中,你正在比較不同的東西。這是需要時間的push。您的代碼與比較eachmap無關。

1

不是絕對的,但表示:

require 'fruity' 

def mapit(a) 
    a.map {|e| e + 2}.size 
end 

def eachit(a) 
    result = [] 
    a.each do |e| 
    result.push(e + 2) 
    end.size 
end 

a = Array.new(1_000) { rand 10 } 
compare do 
    map { mapit(a) } 
    each { eachit(a) } 
end 
    #=> Running each test 32 times. Test will take about 1 second. 
    #=> map is faster than each by 2x ± 0.1 

a = Array.new(10_000) { rand 10 } 
compare do 
    map { mapit(a) } 
    each { eachit(a) } 
end 
    #=> Running each test 4 times. Test will take about 1 second. 
    #=> map is faster than each by 50.0% ± 10.0% 

a = Array.new(100_000) { rand 10 } 
compare do 
    map { mapit(a) } 
    each { eachit(a) } 
end 
    #=> Running each test once. Test will take about 1 second. 
    #=> map is faster than each by 2x ± 0.1 

這是你的兩個方法的不完善的基準。詢問是否eachmap更快只適用於非常具體的比較。

2

在MRI V2.2.2 This is the source for each

   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; 
} 

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; 
} 

注意mapeach幾乎是相同的(這是可以預料的),但map還需要創建一個數組,然後它推動。Ruby中的each版本基本上是做同樣的事情,但是你的是Ruby,這是C,所以在更高的層次上重新創建更低的層次將會產生額外的開銷,並且C通常比Ruby更快。