4
當我有這個功能能重現我的問題:的OutOfMemoryError使用塞克功能
(defn my-problem
[preprocess count print-freq]
(doseq [x (preprocess (range 0 count))]
(when (= 0 (mod x print-freq))
(println x))))
一切工作正常,當我和身份功能這樣稱呼它:
(my-problem identity 10000000 200000)
;it prints 200000,400000 ... 9800000 just as it should
當我把它與seque函數我得到OutOfMemoryError:
(my-problem #(seque 5 %) 10000000 200000)
;it prints numbers up to 2000000 and then it throws OutOfMemoryException
我的理解是seq ue函數應該使用最大大小爲5的ConcurrentBlockingQueue將處理拆分爲兩個線程(在這種情況下)。我不明白內存泄漏的位置。
我很困惑這個答案。我從來沒有太多的理由去研究seque,但我認爲這個想法是,如果消費者領先於製片人,而不是堆積請求,他會被阻止。對我來說,內存錯誤對於實現的巨大範圍來說似乎更合理(引用在seque中關閉)。 –
這就是這個想法,但是如果你仔細閱讀了實現(我花了很多時間來追蹤相關的錯誤),你會發現這確實發生了:['drain'](https:/ /github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L4971)每次消耗一個物品都會添加一個代理任務,而'fill'允許單個代理任務添加多個物品,如果隊列未滿。最終,可以有多個代理任務掛起,因爲輸入序列中有項目。 – amalloy
@ A.Webb,如果你想要更有說服力的證據,試着運行'(dorun(seque(range)))',然後用'jmap -histo'來查看佔用所有堆空間的內容。這都是哈希映射和代理動作 - 很少有空間是懶惰的seq對象。 –
amalloy