【问题标题】:Why is this Scala code slow?为什么这个 Scala 代码很慢?
【发布时间】:2012-03-05 10:45:47
【问题描述】:

我正在运行以下 Scala 代码:

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

在我的机器上,http://sortable.com/blog/coding-challenge/ 的文件大约需要 3 分钟。我编写的等效 Haskell 和 Ruby 程序只用了不到 4 秒。我做错了什么?

我尝试了没有 map(jsonStringMap) 的相同代码,它非常快,那么 JSON 解析器真的很慢吗?

默认的 JSON 解析器似乎确实很慢,但是我尝试了 https://github.com/stevej/scala-json,虽然这将其缩短到 35 秒,但仍然比 Ruby 慢得多。

我现在使用的是https://github.com/codahale/jerkson,它更快!我的程序现在在我的数据上运行只需 6 秒,仅比 Ruby 慢 3 秒,这可能只是 JVM 启动。

【问题讨论】:

  • 也许更适合 codereview.stackexchange.com
  • 副手,似乎您正在独立解析每一行。您是否尝试过为整个 JSON 文档调用一次解析器?
  • 我很确定答案只是“没有人费心编写快速 JSON 解析器”。解析器组合器(JSON 解析器就是其中之一)是为了易于创建,而不是性能。如果您想要速度,最好使用 Java JSON 库。
  • 提升 json 必须很快,正如这个问题的答案中所引用的 stackoverflow.com/questions/927983/…
  • 好吧,如果我们能看到 Ruby/Haskell 程序就更容易回答了。

标签: json performance scala


【解决方案1】:

快速浏览一下 scala-user 存档似乎表明没有人认真使用 scala 标准库中的 JSON 解析器。

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

似乎解析器最终出现在标准库中的时候,scala 不太受关注,也没有今天的期望。

【讨论】:

    【解决方案2】:

    使用Jerkson。 Jerkson 使用 Jackson,它始终是 JVM 上最快的 JSON 库(尤其是在流式读/写时)大型文档。

    【讨论】:

    • 根据链接,该项目已经放弃了。
    【解决方案3】:

    使用my JSON library,我几乎可以立即解析这两个文件:

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

    但是,正如有人提到的,将整个内容解析为 JSONArray 而不是像这样有很多单独的行会更有用。

    【讨论】:

      猜你喜欢
      • 2010-10-19
      • 2011-03-27
      • 2011-05-07
      • 2020-11-01
      • 1970-01-01
      • 2017-01-10
      • 2011-08-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多