2012-02-23 39 views
7

biegnę następujący kod Scala:Dlaczego ten kod Scala jest wolny?

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 
       } 
     } 
} 

Na moim komputerze trwa około 3 minut na pliku z http://sortable.com/blog/coding-challenge/. Odpowiednik programów Haskell i Ruby, które napisałem, trwa poniżej 4 sekund. Co ja robię źle?

Próbowałem tego samego kodu bez mapy (jsonStringMap) i było szybko, więc czy parser JSON jest naprawdę wolny?

Wydaje się prawdopodobne, że domyślny analizator składni JSON jest po prostu bardzo powolny, jednak spróbowałem https://github.com/stevej/scala-json, a podczas gdy osiągnie to 35 sekund, to nadal jest znacznie wolniejsze niż Ruby.

Używam teraz https://github.com/codahale/jerkson, który jest jeszcze szybszy! Mój program działa teraz tylko 6 sekund na moich danych, tylko 3 sekundy wolniej niż Ruby, co jest prawdopodobnie tylko uruchomieniem JVM.

+0

może lepiej pasuje do codereview.stackexchange.com – Nettogrof

+0

Z drugiej strony wygląda na to, że analizujesz każdą linię niezależnie. Czy próbowałeś raz wywołać analizator składni dla całego dokumentu JSON? –

+0

@ChrisShain Mógłbym przekształcić cały plik w dokument JSON, ale (a) nie widzę, jak to by było szybciej, ponieważ nie może przesyłać strumieniowo linii z pliku nawet, ale musiałby zrobić to wszystko od razu (b) dlaczego robienie tego samego, co robi w Ruby, jest o wiele szybsze? – singpolyma

Odpowiedz

8

Szybkie spojrzenie na archiwum scala-user wydaje się wskazywać, że nikt nie robi poważnej pracy z parserem JSON w standardowej bibliotece scala.

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

Wydaje parsera znalazł się w standardowej bibliotece w czasie, kiedy Scala była mniejsza w świetle reflektorów i nie mają oczekiwania w dniu dzisiejszym.

2

Korzystanie my JSON library, mam niemal natychmiastowe parse zarówno pliki:

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") 

Jednak, jak ktoś wspomniał, byłoby bardziej użyteczne tylko analizować całość jako JSONArray zamiast mieć wiele indywidualnych linie jak to robi.

3

Użyj Jerkson. Jerkson używa Jackson'a, który jest zawsze najszybszą biblioteką JSON na maszynie JVM (zwłaszcza podczas odczytywania/zapisywania strumieniowego) dużych dokumentów.

+0

Zgodnie z linkiem projekt został porzucony. – null

Powiązane problemy