在对某些Clojure代码进行压力测试时,我发现在迭代大型数据集时,它会耗尽堆空间。我最终设法将问题追溯到Clojure的doseq
函数和懒惰序列的实现组合。
这是通过耗尽可用堆空间来崩溃Clojure的最小代码段:
(doseq [e (take 1000000000 (iterate inc 1))] (identity e))
doseq
的文档明确指出它不会保留延迟序列的头部,所以我希望上面代码的内存复杂性接近于O(1)。有什么我想念的吗?如果doseq
无法完成工作,那么迭代非常大的惰性序列的Clojure惯用方法是什么?
答案 0 :(得分:2)
当我运行这个示例时,我看到内存使用量达到2.0 Gigs,所以也许你实际上只是用完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