使用net.liftweb.json或scala.util.parsing.json解析大型(30MB)JSON文件会产生OutOfMemoryException.有什么建议?

jal*_*ley 13 json scala lift

我有一个包含大量测试数据的JSON文件,我想要解析并推送我正在测试的算法.它的大小约为30MB,列表中有大约60,000个元素.我最初尝试使用scala.util.parsing.json中的简单解析器,如下所示:

import scala.util.parsing.json.JSON
val data = JSON.parseFull(Source.fromFile(path) mkString)
Run Code Online (Sandbox Code Playgroud)

其中path只是一个包含大JSON文件路径的字符串.那拉了大约45分钟,然后扔了这个:

java.lang.OutOfMemoryError: GC overhead limit exceeded
Run Code Online (Sandbox Code Playgroud)

然后有人向我指出没有人使用这个库,我应该使用Lift的JSON解析器.所以我在Scala REPL中尝试了这个:

scala> import scala.io.Source
import scala.io.Source

scala> val s = Source.fromFile("path/to/big.json")
s: scala.io.BufferedSource = non-empty iterator

scala> val data = parse(s mkString)
java.lang.OutOfMemoryError: GC overhead limit exceeded
Run Code Online (Sandbox Code Playgroud)

这次只花了大约3分钟,但同样的错误.

因此,显然我可以将文件分解为较小的文件,迭代JSON文件的目录并将我的数据一块一块地合并在一起,但是如果可能的话我宁愿避免使用它.有没有人有任何建议?

有关详细信息 - 过去几周我一直在使用Clojure中的相同数据集(用于与Incanter进行可视化)而没有任何问题.以下工作完全正常:

user=> (use 'clojure.data.json)
nil
user=> (use 'clojure.java.io)
nil

user=> (time (def data (read-json (reader "path/to/big.json"))))
"Elapsed time: 19401.629685 msecs"
#'user/data
Run Code Online (Sandbox Code Playgroud)

Jon*_*han 9

这些消息表明该应用程序花费超过98%的时间来收集垃圾.

我怀疑Scala会产生很多短暂的物体,这就是造成过多GC的原因.您可以通过添加-verbosegc命令行开关来验证GC性能java.

Java 1.5+服务器VM上的默认最大堆大小为1 GB(或已安装内存的1/4,以较小者为准),这应该足以满足您的需要,但您可能希望增加新一代以查看是否有所改进你的表现.在Oracle VM上,可以使用该-Xmn选项完成此操作.尝试设置以下环境变量:

$JAVA_OPTS=-server -Xmx1024m -Xms1024m -Xmn2m -verbosegc -XX:+PrintGCDetails
Run Code Online (Sandbox Code Playgroud)

并重新运行您的应用程序.

您还应该查看此调整指南以获取详细信息.