我有一个包含大量测试数据的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
答案 0 :(得分:9)
这些消息表明应用程序正在花费more than 98% of its time收集垃圾。
我怀疑Scala会产生很多短命的物体,这就是造成过多GC的原因。您可以通过将-verbosegc
命令行开关添加到java
来验证GC性能。
Java 1.5+服务器VM上的default max heap size是1 GB(或已安装内存的1/4,以较少者为准),这应该足以满足您的需要,但您可能希望将新一代增加到看看这是否能提高你的表现。在Oracle VM上,使用-Xmn
选项完成此操作。尝试设置以下环境变量:
$JAVA_OPTS=-server -Xmx1024m -Xms1024m -Xmn2m -verbosegc -XX:+PrintGCDetails
并重新运行您的应用程序。
您还应该查看this tuning guide了解详情。
答案 1 :(得分:3)