Подтвердить что ты не робот

Разбор большого (30 МБ) файла JSON с net.liftweb.json или scala.util.parsing.json дает OutOfMemoryException. Любые рекомендации?

У меня есть файл JSON, содержащий довольно много тестовых данных, которые я хочу проанализировать и протестировать через алгоритм, который я тестирую. Это около 30 МБ, со списком из 60 000 элементов. Сначала я попробовал простой парсер в scala.util.parsing.json, например:

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

Где путь - это просто строка, содержащая путь к большому файлу 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
4b9b3361

Ответ 1

Эти сообщения указывают, что приложение тратит более 98% своего времени на сбор мусора.

Я подозреваю, что Scala генерирует много короткоживущих объектов, что и вызывает чрезмерные GC. Вы можете проверить производительность GC, добавив переключатель командной строки -verbosegc в java.

размер максимальной кучи по умолчанию на Java 1.5+ сервер VM составляет 1 ГБ (или 1/4 установленной памяти, в зависимости от того, что меньше), что должно быть достаточным для ваших целей, но вы можете захотеть увеличить новое поколение, чтобы убедиться, что это повышает вашу производительность. В Oracle VM это делается с помощью опции -Xmn. Попробуйте установить следующую переменную среды:

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

и перезапустите приложение.

Вы также можете проверить этот руководство по настройке.

Ответ 2

Попробуйте вместо Jerkson. Jerkson использует Jackson под ним, который многократно оценивается как самый быстрый и эффективный с точки зрения эффективности анализатор JSON на JVM.

Я использовал как Lift JSON, так и Jerkson в производстве, а производительность Jerkson была значительно лучше, чем Lift (особенно при разборе и создании больших документов JSON).