不同的無限循環(在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佔用率的原因。但爲什麼首先會有這樣的記憶差異?
不同的無限循環(在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佔用率的原因。但爲什麼首先會有這樣的記憶差異?
功能range
創建一個惰性序列。懶序列僅按需創建元素。如果懶惰seq的開始被綁定到某個變量(本地使用let
或全局使用def
),則seq將緩存其所有元素並因此消耗內存。這通常被稱爲「保持序列的頭部」。
這就是爲什麼你的第二個例子消耗大量內存。
我期望用jvisualvm進行分析可以發現,clojure本身並不消耗CPU週期,而是嘗試應對不斷增加的內存使用量的JVM。
最後,count
遍歷整個序列,從而實現所有元素。在僅僅(range)
的情況下,該序列永遠不會結束,當沒有更多存儲器可用時它會停止。
他們爲什麼要緩存?它是用於記憶表演嗎? –
@KevinKostlan因爲一個序列可能會產生一個包含當前時間的元素。這意味着如果你不存儲物化數據,那麼在同一個*序列上的第二次迭代將產生不同的結果。 – zerkms
'count'在計數時不保留數據。但是通過'def',物化數據被'x'變量保留。 – zerkms