Анализ большого (30 МБ) файла JSON с помощью net.liftweb.json или scala.util.parsing.json дает исключение OutOfMemoryException. Любые рекомендации? - PullRequest
13 голосов
/ 17 января 2012

У меня есть файл JSON, содержащий довольно много тестовых данных, которые я хочу проанализировать и протолкнуть через алгоритм, который я тестирую. Это около 30 МБ, со списком из 60000 элементов. Сначала я попробовал простой синтаксический анализатор в 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

Кто-то тогда указал мне, что никто не использует эту библиотеку, и я должен использовать JSON-анализатор Lift. Я попробовал это в моем 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

Ответы [ 2 ]

9 голосов
/ 17 января 2012

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

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

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

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

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

Вам также следует проверить это руководство по настройке для получения подробной информации.

3 голосов
/ 17 февраля 2012

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

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

...