Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Memory 在Clojure中处理大量序列时,如何避免堆内存耗尽?_Memory_Clojure_Jvm_Heap_Sequence - Fatal编程技术网

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

Memory 在Clojure中处理大量序列时,如何避免堆内存耗尽?,memory,clojure,jvm,heap,sequence,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)))

我正在尝试生成一个序列,对应于一个非常宽、很深的树的广度优先搜索。。。当我在序列中走得太远时,我就会遇到记忆问题。在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)))
两者都给我一个“OutOfMemoryErrorJava堆空间”。我在MacBookAir上以Eclipse/逆时针方向从REPL运行它们

我对Clojure还很陌生,所以在一天的时间里,我一直希望这是一件我忽略的小事。我意识到我可以增大堆的大小以减少问题的发生,但是我最终想要处理的序列太多了,我认为这对我没有帮助

我试着用“掉”来代替“拿”(在上面的例子中),以避免抓住头部-这没有什么区别。

我错过了多伦。 问题似乎出在StringBuilder str上

如果我按以下方式替换“获取子对象”,则此操作有效:

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

您的JVM内存选项如何?>=Xmx2g?这有助于降低问题发生的可能性,但它仍然会发生在后面,不是吗?当repl尝试打印序列时,它会抓住头部。一个常见的习惯用法是对巨大的惰性seq进行排序,然后一次打印一个元素。我有一个替代的解决方案,这似乎是可行的-要点是用列表上的conj替换str,然后使用doseq和print,而不是直接评估(取200000…)。请忽略我之前的评论-我错过了dorun。使用上面的get children的替代实现,它避免了str,确保了这个实现在整个过程中都是懒惰的。我会删除我的q,然后没有人会知道。。。(感谢你找到了这个问题的根源——有趣的问题,但我仍然不知道为什么修复程序能解决问题)恐怕对我不起作用——我仍然会遇到一个OutOfMemoryError。我认为这里的问题实际上与Clojure无关:它与算法有关。我正在维护一系列条目;每次我取下一个,我就加上它的子项,这样序列就增加了2个条目。最终,这将导致内存溢出。我怀疑通过添加到现有序列,而不是为每个条目创建一个新字符串,您的实现会持续更长的时间。Tom,您的内存耗尽了多少?我尝试了20000000,但堆栈而不是堆用完了。我怀疑这是由于递归调用的缘故。使用recur也可以解决这个问题。