Scala解析器组合器,大文件问题

13

我已经编写了以下解析器:

class LogParser extends JavaTokenParsers {

  def invertedIndex: Parser[Array[Array[(Int, Int)]]] = {
    num ~> num ~> num ~> rep(postingsList) ^^ {
      _.toArray
    }
  }

  def postingsList: Parser[Array[(Int, Int)]] = {
    num ~> rep(entry) ^^ {
      _.toArray
    }
  }

  def entry = {
    num ~ "," ~ num ^^ {
      case docID ~ "," ~ count => (docID.toInt, count.toInt)
    }
  }

  def num = wholeNumber ^^ (_.toInt)

}

如果我通过FileReader以如下方式从一个大小为270MB的文件中解析:

val index = parseAll(invertedIndex, new FileReader("path/to/file")).get

我收到了一个Exception in thread "main" java.lang.StackOverflowError的错误(我也尝试过使用BufferedReader),但我可以通过先将文件读入字符串中来解决:

val input = io.Source.fromFile("path/to/file")
val str = input.mkString
input.close()
val index = parseAll(invertedIndex, str).get

为什么会这样?有没有办法避免先将其读入为字符串,这似乎很浪费?


2
你的堆栈当前大小是多少?为了避免StackOverflowException,你需要将堆栈增加多少?为了使String版本溢出,堆栈必须缩小多少?(你可以通过这样启动来设置16MB的堆栈:scala -J-Xss16M - DaoWen
我之前只是使用默认的堆栈大小,但当我将其设置为16M时,程序仍在运行30分钟后... - Robert
1
这可能与Scala 2.9.2 bug [SI-6520] (https://issues.scala-lang.org/browse/SI-6520)有关。 - Don Roby
看着 @DonRoby 喜欢的 bug,思考解析器组合子的工作原理,我认为回溯机制需要解析器将整个文件存储在内存中才能启用回溯。这听起来像是 PagedSeq 的一个 bug,所以最好将其读入字符串中。 - DaoWen
我之前遇到过这个问题,并且也使用了字符串解决方法。我还刚刚创建了一个新的问题(SI-6612;其中包含一个不是解析组合器特定的示例),因为这似乎与SI-6520非常不同——问题是堆栈溢出,而不是内存耗尽。 - Travis Brown
1个回答

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接