2012-01-17 5 views
13

Tengo un archivo JSON que contiene una gran cantidad de datos de prueba, que quiero analizar y ejecutar a través de un algoritmo que estoy probando. Tiene unos 30 MB de tamaño, con una lista de 60 000 o más elementos. Al principio me probé el analizador simple en scala.util.parsing.json, así:Al analizar un archivo JSON grande (30 MB) con net.liftweb.json o scala.util.parsing.json se obtiene OutOfMemoryException. ¿Alguna recomendación?

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

donde ruta es sólo una cadena que contiene la ruta del archivo grande JSON. Que se bebió de distancia durante unos 45 minutos, luego se arrojó esto:

java.lang.OutOfMemoryError: GC overhead limit exceeded 

Alguien entonces me señaló que nadie utiliza esta biblioteca y que debería utilizar JSON analizador de elevación. Así que probé esto en mi 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 

Esta vez solo tardó unos 3 minutos, pero el mismo error.

Así que, obviamente, podría romper el archivo hasta en los más pequeños, iterar sobre el directorio de archivos JSON y combinar mis datos en conjunto pieza por pieza, pero prefiero evitarlo si es posible. ¿Alguien tiene alguna recomendación?

Para obtener más información: he estado trabajando con este mismo conjunto de datos las últimas semanas en Clojure (para la visualización con Incanter) sin problemas. Los siguientes funciona perfectamente bien:

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 

Respuesta

9

Estos mensajes indican que la aplicación está gastando more than 98% of its time la recogida de basura.

Sospecho que Scala está generando una gran cantidad de objetos efímeros, que es lo que está causando los GC excesivos. Puede verificar el rendimiento del GC agregando el interruptor de línea de comando -verbosegc al java.

El default max heap size en el servidor Java 1.5+ VM es 1 GB (o 1/4 de memoria instalada, cualquiera que sea menor), lo que debería ser suficiente para sus propósitos, pero es posible que desee aumentar la nueva generación para ver si mejora tu rendimiento En Oracle VM, esto se hace con la opción -Xmn. Intente establecer la siguiente variable de entorno:

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

y vuelva a ejecutar su aplicación.

También debe consultar this tuning guide para más detalles.

+0

me corrieron: $ JAVA_OPTS = "- Xmx1024m -Xms1024m -Xmn2m" Scala -classpath levantar-json_2.9.0-1-2.4.jar: paranamer-2.1.jar tomó más tiempo, pero esta vez lo consiguió: java.lang.OutOfMemoryError: espacio de montón de Java Trataré también de aumentar el espacio de montón y publicar de nuevo. Gracias por la respuesta completa en cualquier caso. ¡Enlaces útiles! – jaley

+1

¡OK!con el tamaño de almacenamiento dinámico en 2 gb y las otras opciones que usted propuso, funciona. Toma aproximadamente 10 minutos analizar el archivo y usa mucha memoria, lo cual es un poco molesto, pero para esta prueba de rendimiento automatizada es aceptable. ¡Gracias por tu ayuda! – jaley

+1

No hay problema. ¡Ese desempeño es abismal! – Jonathan

3

Pruebe usar Jerkson en su lugar. Jerkson usa Jackson debajo, que puntúa repetidamente como el analizador JSON más rápido y eficiente de la memoria en la JVM.

He utilizado tanto Lift JSON como Jerkson en producción, y el rendimiento de Jerkson fue significativamente mejor que el de Lift (especialmente al analizar y generar grandes documentos JSON).

+1

El proyecto está abandonado. Consulte esta publicación para obtener una excelente lista de alternativas: http://engineering.ooyala.com/blog/comparing-scala-json-libraries – pjvds

Cuestiones relacionadas