【问题标题】:Clojure GC overhead limit exceeded when using iterate使用迭代时超出 Clojure GC 开销限制
【发布时间】:2017-02-26 19:42:19
【问题描述】:

抱歉重复,但我无法通过阅读其他帖子来解决这个问题。我正在尝试运行计算密集型迭代算法。下一次迭代由函数“update”给出,我通过

收集所有迭代
(def iterates (doall (take 1000 (iterate update initial-state))))

初始状态是我初始化算法的第零次迭代。不幸的是我不能提供一个最小的例子......更新是一个相当复杂的函数,它以地图数据结构作为输入并输出更新的地图数据结构。代码在高达 800 次的总迭代中运行良好,但对于任何更大的迭代都会产生以下错误。一般的观点是仅仅增加垃圾收集器可用的大小是不够的,因为这是一个更深层次问题的症状(也许)。在其他帖子中,提出的问题非常具体,但我的更新功能非常复杂。那么我该如何解决这里提供的一般性呢?我可以使用某些工具实用程序吗?

  1. 由 java.lang.OutOfMemoryError 引起 超出 GC 开销限制

           Double.java:  519  java.lang.Double/valueOf
          Numbers.java:  611  clojure.lang.Numbers$DoubleOps/multiply
          Numbers.java:  148  clojure.lang.Numbers/multiply
              core.clj:   21  ssm4clj.core/corr
              core.clj:    6  ssm4clj.core/corr
              core.clj:   42  ssm4clj.core/innovation
              core.clj:   40  ssm4clj.core/innovation
              core.clj: 2522  clojure.core/partial/fn
              core.clj: 2646  clojure.core/map/fn
          LazySeq.java:   40  clojure.lang.LazySeq/sval
          LazySeq.java:   49  clojure.lang.LazySeq/seq
               RT.java:  521  clojure.lang.RT/seq
              core.clj:  137  clojure.core/seq
              core.clj: 2654  clojure.core/map/fn
          LazySeq.java:   40  clojure.lang.LazySeq/sval
          LazySeq.java:   49  clojure.lang.LazySeq/seq
             Cons.java:   39  clojure.lang.Cons/next
               RT.java:  688  clojure.lang.RT/next
              core.clj:   64  clojure.core/next
         protocols.clj:  168  clojure.core.protocols/fn
         protocols.clj:  124  clojure.core.protocols/fn
         protocols.clj:   19  clojure.core.protocols/fn/G
         protocols.clj:   31  clojure.core.protocols/seq-reduce
         protocols.clj:   75  clojure.core.protocols/fn
         protocols.clj:   75  clojure.core.protocols/fn
         protocols.clj:   13  clojure.core.protocols/fn/G
              core.clj: 6545  clojure.core/reduce
              core.clj: 6527  clojure.core/reduce
              core.clj:  347  ssm4clj.core/mean-conditional
              core.clj:  319  ssm4clj.core/mean-conditional
                  REPL:  332  ipp4clj.multiplexing/update-single-gp-mean
                  REPL:  329  ipp4clj.multiplexing/update-single-gp-mean
    

【问题讨论】:

  • 一组 1000 个状态会占用多少内存?您是否可能根本没有足够的 RAM 来保存这么多数据以及您正在进行的计算所产生的额外垃圾?
  • 您需要所有状态,还是只需要一个达到目标的状态?我想知道您是否可以使用droptake 来丢弃状态?还是drop-while 结合first
  • @SamEstep,当我“置顶”进程时,%MEM 列中的百分比大约为 30 用于有问题的进程。检查顶部的文档,%MEM 显示任务当前使用的可用物理内存份额。据我了解,该进程仅使用了我 30% 的 RAM。
  • @Lindon 是的,你是对的;我忘记了 JVM 内存还有其他限制。你的 RAM 的 30% 是多少?如here 所述,您可能需要增加最大堆大小。但我的问题仍然存在:一组 1000 个状态会占用多少内存?由于您没有指定您的状态结构和update 函数,因此没有这些信息我们无法真正做出判断。
  • 试过用 jvisualvm 查看正在运行的 JVM 进程吗?对于 Oracle JDK,它包含在内,对于 OpenJDK,它通常是一个单独的包。

标签: java clojure garbage-collection


【解决方案1】:

赞同@StefanKamphausen 的评论。我认为 jvisualvm 也会帮助你很多。 Here 是使用说明。

【讨论】:

    猜你喜欢
    • 2011-05-21
    • 2017-12-27
    • 2013-07-13
    • 2018-03-29
    • 2012-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多