在Clojure中处理大量序列时,如何避免耗尽堆内存?

时间:2012-06-08 11:23:45

标签: memory clojure jvm heap sequence

我正在尝试生成一个序列,该序列对应于一个非常宽的深树的广度优先搜索...当我沿着序列走得太远时,我遇到了记忆问题。在询问IRC频道并查看此处之后,这些问题的第一个原因是无意中抓住了头部;但我看不出我在做什么。

代码非常简单;这是一个显示问题的版本:

(def atoms '(a b c))

(defn get-ch [n] (map #(str n %) atoms)) 

(defn add-ch 
  ([] (apply concat (iterate add-ch atoms))) 
  ([n] (mapcat get-ch n)))

(dorun (take 20000000 (add-ch)))

这是另一个版本(这是我从#clojure获得帮助之前开始的那个版本),它显示了同样的问题:

(def atoms '(a b c))

(defn get-children [n] (map #(str n %) atoms))

(defn add-layer 
  ([] (add-layer atoms)) 
  ([n] (let [child-nodes (mapcat get-children n) ] 
      (lazy-seq (concat n (add-layer child-nodes))))))

(dorun (take 20000000 (add-layer)))

两者都给我一个“OutOfMemoryError Java堆空间”。我正在使用Eclipse / CounterClockwise中的REPL在Macbook Air上运行它们。

我对Clojure很陌生,所以在对抗这一天之后,我希望这是一件微不足道的事情,我忽视了。我意识到我可以增加堆大小以使问题不太可能发生,但我最终想要处理的序列是如此巨大,我不认为这会对我有所帮助。

我尝试用“drop”替换“take”(在上面的示例中),以避免保持头部 - 这没有任何区别。

1 个答案:

答案 0 :(得分:2)

我错过了dorun。 问题似乎与StringBuilder str。

有关

如果我将get-children替换为以下内容,则此方法有效:

 (defn get-children [n] (map #(if (seq? n) (conj n %) (conj (list n) %)) atoms))