Clojure 简单惰性seq上的doseq耗尽了堆空间
在工作中对一些Clojure代码进行压力测试时,我注意到它在迭代大型数据集时耗尽了堆空间。我最终设法将问题追溯到Clojure的Clojure 简单惰性seq上的doseq耗尽了堆空间,clojure,lazy-sequences,Clojure,Lazy Sequences,在工作中对一些Clojure代码进行压力测试时,我注意到它在迭代大型数据集时耗尽了堆空间。我最终设法将问题追溯到Clojure的doseq函数和延迟序列的实现的组合 这是通过耗尽可用堆空间使Clojure崩溃的最小代码段: (doseq [e (take 1000000000 (iterate inc 1))] (identity e)) doseq的文档清楚地表明,它没有保留惰性序列的头部,因此我预计上述代码的内存复杂性接近O(1)。有什么我遗漏的吗?如果doseq不能胜任这项工作,那么Cl
doseq
函数和延迟序列的实现的组合
这是通过耗尽可用堆空间使Clojure崩溃的最小代码段:
(doseq [e (take 1000000000 (iterate inc 1))] (identity e))
doseq
的文档清楚地表明,它没有保留惰性序列的头部,因此我预计上述代码的内存复杂性接近O(1)。有什么我遗漏的吗?如果doseq
不能胜任这项工作,那么Clojure惯用的迭代超大延迟序列的方式是什么?当我运行此示例时,我看到内存使用率达到2.0 Gig,因此可能您实际上只是耗尽了ram
确实需要一段时间才能运行:
user=> (time (doseq [e (take 1000000000 (iterate inc 1))] (identity e)))
"Elapsed time: 266396.221132 msecs"
表格顶部:
23999 arthur 20 0 4001m 1.2g 5932 S 213 15.3 17:11.35 java
24017 arthur 20 0 3721m 740m 5548 S 88 9.3 13:49.95 java
您使用的是哪个clojure版本和java运行时?在OSX上使用clojure 1.4/java 1.6.0!33在干净的repl中运行该代码显示完全静态的内存使用量不到400毫巴,您确定这正是导致问题的代码片段吗?在我的机器上运行良好(Clojure 1.4、JDK7、Windows、Eclipse/CCW)。如果你以某种方式抓住了序列的开头,例如如果(iterate inc 1)存储在其他地方,这将是一个问题。你们都是对的,当我关闭Leiningen 2添加到REPL的东西(历史记录、键导航等)并使用香草Clojure 1.4时,问题就消失了。谢谢