xml-parsing - Clojure Leining REPL OutOfMemoryError Java 堆空间

标签 xml-parsing clojure out-of-memory clojure-java-interop

我正在尝试解析一个相当小的(< 100MB)xml 文件:

(require '[clojure.data.xml :as xml]
         '[clojure.java.io :as io])

(xml/parse (io/reader "data/small-sample.xml"))

我收到一个错误:
OutOfMemoryError Java heap space
    clojure.lang.Numbers.byte_array (Numbers.java:1216)
    clojure.tools.nrepl.bencode/read-bytes (bencode.clj:101)
    clojure.tools.nrepl.bencode/read-netstring* (bencode.clj:153)
    clojure.tools.nrepl.bencode/read-token (bencode.clj:244)
    clojure.tools.nrepl.bencode/read-bencode (bencode.clj:254)
    clojure.tools.nrepl.bencode/token-seq/fn--3178 (bencode.clj:295)
    clojure.core/repeatedly/fn--4705 (core.clj:4642)
    clojure.lang.LazySeq.sval (LazySeq.java:42)
    clojure.lang.LazySeq.seq (LazySeq.java:60)
    clojure.lang.RT.seq (RT.java:484)
    clojure.core/seq (core.clj:133)
    clojure.core/take-while/fn--4236 (core.clj:2564)

这是我的project.clj:
(defproject dats "0.1.0-SNAPSHOT"
  ...
  :dependencies [[org.clojure/clojure "1.5.1"]
                [org.clojure/data.xml "0.0.7"]
                [criterium "0.4.1"]]
  :jvm-opts ["-Xmx1g"])

我尝试在我的 .bash_profile 中设置 LEIN_JVM_OPTS 和 JVM_OPTS 但没有成功。

当我尝试以下 project.clj 时:
(defproject barber "0.1.0-SNAPSHOT"
  ...
  :dependencies [[org.clojure/clojure "1.5.1"]
                [org.clojure/data.xml "0.0.7"]
                [criterium "0.4.1"]]
  :jvm-opts ["-Xms128m"])

我收到以下错误:
Error occurred during initialization of VM
Incompatible minimum and maximum heap sizes specified
Exception in thread "Thread-5" clojure.lang.ExceptionInfo: Subprocess failed {:exit-code 1}

知道如何增加我的 leiningen repl 的堆大小吗?

谢谢。

最佳答案

作为 Read-Eval-Print-Loop 的打印步骤的结果,在 repl 的顶层评估的任何形式都将完全实现。它也存储在堆中,以便您以后可以通过 *1 访问它。

如果您按如下方式存储返回值:
(def parsed (xml/parse (io/reader "data/small-sample.xml")))
这会立即返回,即使是数百兆字节的文件(我已经在本地验证了这一点)。然后,您可以通过遍历返回的 clojure.data.xml.Element 树来遍历结果,该结果在从输入流中解析时完全实现。

如果您不保留元素(通过绑定(bind)它们以便它们仍然可以访问),则可以迭代整个结构,而无需使用比保留 xml 树的单个节点所需的更多内存。

user> (time (def n (xml/parse (clojure.java.io/reader "/home/justin/clojure/ok/data.xml"))))
"Elapsed time: 0.739795 msecs"
#'user/n
user> (time (keys n))
"Elapsed time: 0.025683 msecs"
(:tag :attrs :content)
user> (time (-> n :tag))
"Elapsed time: 0.031224 msecs"
:catalog
user> (time (-> n :attrs))
"Elapsed time: 0.136522 msecs"
{}
user> (time (-> n :content first))
"Elapsed time: 0.095145 msecs"
#clojure.data.xml.Element{:tag :book, :attrs {:id "bk101"}, :content (#clojure.data.xml.Element{:tag :author, :attrs {}, :content ("Gambardella, Matthew")} #clojure.data.xml.Element{:tag :title, :attrs {}, :content ("XML Developer's Guide")} #clojure.data.xml.Element{:tag :genre, :attrs {}, :content ("Computer")} #clojure.data.xml.Element{:tag :price, :attrs {}, :content ("44.95")} #clojure.data.xml.Element{:tag :publish_date, :attrs {}, :content ("2000-10-01")} #clojure.data.xml.Element{:tag :description, :attrs {}, :content ("An in-depth look at creating applications \n      with XML.")})}
user> (time (-> n :content count))
"Elapsed time: 48178.512106 msecs"
459000
user> (time (-> n :content count))
"Elapsed time: 86.931114 msecs"
459000
;; redefining n so that we can test the performance without the pre-parsing done when we counted
user> (time (def n (xml/parse (clojure.java.io/reader "/home/justin/clojure/ok/data.xml"))))
"Elapsed time: 0.702885 msecs"
#'user/n
user> (time (doseq [el (take 100 (drop 100 (-> n :content)))] (println (:tag el))))
:book
:book
.... ;; output truncated
"Elapsed time: 26.019374 msecs"
nil
user> 

请注意,只有当我第一次询问 n 的内容计数(从而强制解析整个文件)时,才会出现巨大的时间延迟。如果我对结构的各个部分进行剂量,这会很快发生。

关于xml-parsing - Clojure Leining REPL OutOfMemoryError Java 堆空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18094278/

相关文章:

linux - 为什么 PostgreSQL 在执行长时间运行的 INSERT … SELECT … 时不保存到磁盘?

linux - 在 Linux 上防止内存不足 (OOM) 卡住的最佳方法是什么?

java - 为什么我的 HTC magic 会出现 OutOfMemoryError 异常?

java - Jaxb Unmarshall 找到预期标签并失败,因为它是意外的

javascript - 需要通过 JavaScript 解析 XML 数据的帮助

xml-parsing - 发现以元素 'country' 开头的无效内容。 '{country}' 之一是预期的.. 行 '10' ,列 '14'

recursion - 成员?在无限列表上运行

java - 使用 JDOM 解析 XML 文件,出现错误 StackOverflowError

haskell - 语义(Haskell)受推断类型(返回类型多态性)的影响是什么意思?

java - 如何在对象上调用 setter 方法(强制类型)