2012-02-23 11 views
7

Io corro il seguente codice Scala:Perché questo codice Scala è lento?

import scala.util.parsing.json._ 
import scala.io._ 

object Main { 
     def jsonStringMap(str: String) = 
       JSON.parseFull(str) match { 
         case Some(m: Map[_,_]) => m collect { 
             // If this doesn't match, we'll just ignore the value 
             case (k: String, v: String) => (k,v) 
           } toMap 
         case _ => Map[String,String]() 
       } 

     def main(args: Array[String]) { 
       val fh = Source.fromFile("listings.txt") 
       try { 
         fh.getLines map(jsonStringMap) foreach { v => println(v) } 
       } finally { 
         fh.close 
       } 
     } 
} 

Sulla mia macchina ci vogliono ~ 3 minuti sul file da http://sortable.com/blog/coding-challenge/. I programmi equivalenti di Haskell e Ruby che ho scritto prendono meno di 4 secondi. Che cosa sto facendo di sbagliato?

Ho provato lo stesso codice senza la mappa (jsonStringMap) ed era molto veloce, quindi il parser JSON è davvero lento?

Sembra probabile che il parser JSON predefinito sia solo molto lento, tuttavia ho provato con lo https://github.com/stevej/scala-json e anche se questo scende a 35 secondi, è ancora molto più lento di Ruby.

Ora sto usando https://github.com/codahale/jerkson che è ancora più veloce! Il mio programma ora viene eseguito in soli 6 secondi sui miei dati, solo 3 secondi più lentamente di Ruby, che probabilmente è l'avvio della JVM.

+0

forse un adattamento migliore per codereview.stackexchange.com – Nettogrof

+0

A mano libera, sembra che si stia analizzando ogni riga in modo indipendente. Hai provato a invocare il parser una volta per l'intero documento JSON? –

+0

@ChrisShain Potrei convertire tutto il file in un documento JSON, ma (a) non vedo come sarebbe più veloce, perché non è possibile eseguire lo streaming delle righe dal file, ma dovrebbe fare tutto contemporaneamente (b) perché fare la stessa cosa che sta facendo in Ruby è molto più veloce? – singpolyma

risposta

8

Un rapido sguardo all'archivio di scala utente sembra indicare che nessuno sta facendo un lavoro serio con il parser JSON nella libreria standard di scala.

Vedi http://groups.google.com/group/scala-user/msg/fba208f2d3c08936

sembra che il parser finito nella libreria standard nel momento in cui scala era meno sotto i riflettori e non ha avuto le aspettative che ha oggi.

2

Utilizzando my JSON library, ottengo un parse quasi istantanea di entrambi i file:

import com.github.seanparsons.jsonar._ 
import scala.io.Source 
def parseLines[T](file: String, transform: (Iterator[String]) => T): T = { 
    val log = Source.fromFile(file) 
    val logLines = log.getLines() 
    try { transform(logLines) } finally { log.close } 
} 
def parseFile(file: String) = parseLines(file, (iterator) => iterator.map(Parser.parse(_)).toList) 
parseFile("products.txt"); parseFile("listings.txt") 

Tuttavia, come qualcuno ha detto, sarebbe più utile per analizzare solo il tutto come un JSONArray, piuttosto che avere un sacco di singoli linee come questo.

3

Utilizzare Jerkson. Jerkson usa Jackson, che è sempre la libreria JSON più veloce sulla JVM (specialmente quando legge/scrive in streaming) documenti di grandi dimensioni.

+0

Secondo il link, il progetto è stato abbandonato. – null

Problemi correlati