繁体   English   中英

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

[英]Parsing a large (30MB) JSON file with net.liftweb.json or scala.util.parsing.json gives OutOfMemoryException. Any recommendations?

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

import scala.util.parsing.json.JSON
val data = JSON.parseFull(Source.fromFile(path) mkString)

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

java.lang.OutOfMemoryError: GC overhead limit exceeded

然后有人向我指出没有人使用这个库,我应该使用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

这次只花了大约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

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

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

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

$JAVA_OPTS=-server -Xmx1024m -Xms1024m -Xmn2m -verbosegc -XX:+PrintGCDetails

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

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

尝试使用Jerkson Jerkson在下面使用了Jackson ,它在JVM上反复被评为最快且内存最高效的JSON解析器。

我在生产中使用了Lift JSON和Jerkson,而Jerkson的性能明显优于Lift(特别是在解析和生成大型JSON文档时)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM