在对工作中的某些 Clojure 代码进行压力测试时,我注意到它在迭代大型数据集时会耗尽堆空间。我最终设法将问题追溯到 Clojure 的doseq
函数和惰性序列的实现的组合。
这是通过耗尽可用堆空间使 Clojure 崩溃的最小代码片段:
(doseq [e (take 1000000000 (iterate inc 1))] (identity e))
文档doseq
明确指出它不保留惰性序列的头部,因此我希望上述代码的内存复杂度接近 O(1)。有什么我想念的吗?doseq
如果不能胜任这项工作,那么迭代超大惰性序列的 Clojure 惯用方式是什么?