2

在对工作中的某些 Clojure 代码进行压力测试时,我注意到它在迭代大型数据集时会耗尽堆空间。我最终设法将问题追溯到 Clojure 的doseq函数和惰性序列的实现的组合。

这是通过耗尽可用堆空间使 Clojure 崩溃的最小代码片段:

(doseq [e (take 1000000000 (iterate inc 1))] (identity e))

文档doseq明确指出它不保留惰性序列的头部,因此我希望上述代码的内存复杂度接近 O(1)。有什么我想念的吗?doseq如果不能胜任这项工作,那么迭代超大惰性序列的 Clojure 惯用方式是什么?

4

1 回答 1

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  
于 2012-08-13T22:35:15.880 回答