不同的无限循环(在REPL,clojure 1.7.0):
(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使用量过大的原因。但是为什么首先会有这样的记忆差异呢?
答案 0 :(得分:2)
函数range
创建一个惰性序列。延迟序列仅按需创建其元素。如果lazy seq的开头绑定到某个变量(本地带有let
或全局带有def
),则seq将缓存其所有元素,从而消耗内存。这通常被称为“抓住序列的头部”。
这就是你的第二个例子消耗大量内存的原因。
我希望用jvisualvm进行的分析会显示它本身并不是消耗CPU周期的clojure,而是JVM试图应对不断增加的内存使用量。
最后,count
遍历整个序列,从而实现所有元素。如果只有(range)
,序列将永远不会结束,当没有更多可用内存时它会停止。