【发布时间】:2018-08-02 02:48:23
【问题描述】:
这里是 Clojure 初学者/中级,
我有一个很大的 XML 文件 (~ 240M),为了 ETL 目的,我需要逐项懒惰地处理它。
有一些 run-processing 函数,它做了很多副作用,数据库交互,写入日志等。
当我将上述功能应用于文件时,一切运行顺利:
...
(with-open [source (-> "in.xml"
io/file
io/input-stream)]
(-> source
xml/parse
((fn [x]
;; runs fine
(run-processing conn config x)))))
但是当我将相同的函数放入任何类型的循环(如doseq)时,我会得到 OutOfMemoryException(GC 开销)。
...
(with-open [source (-> "in.xml"
io/file
io/input-stream)]
(-> source
xml/parse
((fn [x]
;; throws OOM GC overhead exception
(doseq [i [0]]
(run-processing conn config x))))))
我不明白,导致GC开销异常的头部保留发生在哪里?我已经尝试过run! 甚至loop recur 而不是doseq——同样的事情发生了。
我的run-processing 函数一定有问题吗?那为什么当我直接运行它时它表现得很好?
有点迷茫,希望有任何帮助。
【问题讨论】:
-
您是否尝试过增加 JVM 堆大小?会不会是,doseq 本身分配的内存刚好够导致 OOM?
-
另外,您不希望将运行处理置于循环中。我想你正在使用 data.xml,它是惰性的,但 x 是一个 seq 头。一旦 run-processing 运行,底层序列就完全实现了,并将在 doseq 的持续时间内保存在内存中。
-
@IgorKharin 所以当我使用任何类型的循环时序列将保存在内存中,但如果我直接调用运行处理则不会?但是在doseq docstring中明确指出“不保留序列的头部”。那么当我需要多次调用 run-processing (例如使用不同的参数)时该怎么办?
-
@nha,我已经尝试使用 dorun 获得相同的结果。在 clojuredocs 上我到底应该注意什么?
标签: clojure out-of-memory lazy-sequences