2016-07-14 46 views
1

不同的無限循環(在REPL,Clojure的1.7.0):Clojure的計數資源利用

(count (range)) ; ~100% of 1 CPU, as expected. 
(def x (range)) 
(count x) ; Over 7 CPUs maxed out, on a 4-core machine (hyper threading?). 

較低的循環還豬的內存,所以不斷的GC可能是巨大的CPU佔用率的原因。但爲什麼首先會有這樣的記憶差異?

+3

'count'在計數時不保留數據。但是通過'def',物化數據被'x'變量保留。 – zerkms

回答

2

功能range創建一個惰性序列。懶序列僅按需創建元素。如果懶惰seq的開始被綁定到某個變量(本地使用let或全局使用def),則seq將緩存其所有元素並因此消耗內存。這通常被稱爲「保持序列的頭部」。

這就是爲什麼你的第二個例子消耗大量內存。

我期望用jvisualvm進行分析可以發現,clojure本身並不消耗CPU週期,而是嘗試應對不斷增加的內存使用量的JVM。

最後,count遍歷整個序列,從而實現所有元素。在僅僅(range)的情況下,該序列永遠不會結束,當沒有更多存儲器可用時它會停止。

+0

他們爲什麼要緩存?它是用於記憶表演嗎? –

+0

@KevinKostlan因爲一個序列可能會產生一個包含當前時間的元素。這意味着如果你不存儲物化數據,那麼在同一個*序列上的第二次迭代將產生不同的結果。 – zerkms