2016-01-21 26 views
-2

這兩個垃圾中的一個是不同的收集方式,還是在他們相同?與.map相比,每個GC都有不同的影響嗎?

array_of_strings.each do |str| 
    MailerClass.some_template(str).deliver_later 
end 

array_of_strings.map do |str| 
    MailerClass.some_template(str).deliver_later 
end 

我格式化郵件的對象和任務隊列的東西的問題,因爲這是我最近被工作,但如果這會過度的答案則更加複雜,我可以改寫爲更通用。


背景下,作爲相關:

我認爲.map將用尖頭返回一個對象所創建的每個 對象,而.each不會。 [這似乎 並非如此]我有職工機泄漏存儲器直到崩潰

- 所有 發生在一個事件,其中該僞碼的例子是 中樞作用。當我改變了它從.each.map那麼 內存泄漏停止了,但我不知道GC是如何在 關於這些方法發生。

+0

爲什麼在這種情況下會使用'map'? –

+0

我認爲'.map'會返回一個指向每個創建對象的對象。 '.each'不會。我有一臺工作機器會在內存泄漏之前崩潰 - 所有這一切都發生在這個僞代碼示例是中心操作的事件中。當我將它從'.each'改爲'.map'時,內存泄漏就停止了,但我不知道GC是由於這些方法而發生的。 –

+1

您可以在運行該循環之前自行計算對象,並在使用http://ruby-doc.org/core-2.2.0/ObjectSpace.html#count_objects-method運行該對象並查看是否分配了更多對象之後,我懷疑是否會有任何區別 – bjhaid

回答

1

由於映射返回一個array_of_strings的每個成員評估塊的結果數組,所以至少會有一個額外的對象被收集。

+0

ruby​​如何跟蹤每個執行的'.each'塊中創建的對象? –

+0

每個塊內創建的任何對象在超出作用域時都會被標記爲GC(每個塊的迭代結束時),除非引用保存在別處,與map相同,除了它將每次迭代的返回值添加到要返回的數組最後。在這種情況下,還會創建郵件作業,將其添加到隊列中,以便對它們的引用保留在隊列中,以便它們不會被標記爲GC。 –

+0

謝謝,儘管發送了類似數量的電子郵件,但我顯然需要更多地考慮爲什麼'.map'解決內存泄漏問題。我希望能夠將這個問題「推向」「.map」的現實,從而創造出一種改進,然後得出原因的答案。 –

1

根據您使用的確切的Ruby實現,Enumerable#map的實現可以使用Ruby,Smalltalk,RPython,ECMAScript,C#,Java,Go,Objective-C,C++,C或任意數量的其他語言編寫,但它的運作總是會看起來像這樣:

module Enumerable 
    def map 
    return enum_for(__method__) unless block_given? 
    [].tap {|result| each {|el| result << yield el }} 
    end 
end 

map必須呼叫each,有簡單的爲它遍歷沒有其他辦法。因此,它將分配與each將分配的確切相同的對象附加結果Array,即恰好比each多一個對象。

實際上,許多Ruby實現覆蓋Enumerable#mapArray#map,這比通用的Enumerable版本更有效。他們通常遍歷直接Array元素,而不調用each,有點像這樣:

class Array 
    def map 
    return enum_for(__method__) unless block_given? 

    result = [] 

    i = -1 
    while i += 1 <= size 
     result << yield @__entries__[i] 
    end 
    end 
end 

這比一般的Enumerable#map更有效,因爲它使用如何才能避免重複的Array專業知識方法調用開銷爲each。但是請注意,這each將在完全相同的方式來實現,除非實現者是令人難以置信的愚蠢,所以最終的結果是一樣的:map仍然會分配恰好一個對象超過each,它只是一個保存方法調用。

請注意,由於您忽略了map的返回值,所以額外的對象將立即適用於垃圾回收。但是,在此之前,它保存對deliver_later方法返回的所有對象的引用,無論它們是什麼。

所以,兩段代碼之間的區別是:

  • eachdeliver_later返回值被忽略,變得適合立即
  • map垃圾收集,還有額外的Array分配它保持塊內所有deliver_later調用的返回值的引用,並因此保持這些對象一直存在,直到調用map返回,然後,Array,因此它引用的所有對象將同時有資格進行垃圾回收
+0

這是一個非常全面和有價值的答案。 –

+0

順便說一句:我試圖找出'deliver_later'的返回值究竟是什麼,通過跟蹤它通過ActionMailer和ActiveJob源代碼,但是在我的瀏覽器中通過GitHub,GitHub Search和Find-on-Page太扭曲了,我不想安裝Rails並將其加載到IDE中。 –

相關問題