【问题标题】:Scala Infinite Iterator OutOfMemoryScala 无限迭代器 OutOfMemory
【发布时间】:2012-01-28 06:21:42
【问题描述】:

我正在使用 Scala 的惰性迭代器,但遇到了一个问题。我正在尝试做的是读取一个大文件,进行转换,然后写出结果:

object FileProcessor {
  def main(args: Array[String]) {
    val inSource = Source.fromFile("in.txt")
    val outSource = new PrintWriter("out.txt")

    try {
      // this "basic" lazy iterator works fine
      // val iterator = inSource.getLines

      // ...but this one, which incorporates my process method, 
      // throws OutOfMemoryExceptions
      val iterator = process(inSource.getLines.toSeq).iterator

      while(iterator.hasNext) outSource.println(iterator.next)

    } finally {
      inSource.close()
      outSource.close()
    }
  }

  // processing in this case just means upper-cases every line
  private def process(contents: Seq[String]) = contents.map(_.toUpperCase)
}

所以我在大文件上遇到 OutOfMemoryException。我知道如果你保留对 Stream 头部的引用,你可能会与 Scala 的惰性 Streams 发生冲突。所以在这种情况下,我小心地将 process() 的结果转换为迭代器并丢弃它最初返回的 Seq。

有谁知道为什么这仍然会导致 O(n) 内存消耗?谢谢!


更新

针对 fge 和 huynhjl,似乎 Seq 可能是罪魁祸首,但我不知道为什么。例如,以下代码可以正常工作(而且我到处都在使用 Seq)。这段代码不会产生 OutOfMemoryException:

object FileReader {
  def main(args: Array[String]) {

  val inSource = Source.fromFile("in.txt")
  val outSource = new PrintWriter("out.txt")
  try {
    writeToFile(outSource, process(inSource.getLines.toSeq))
  } finally {
    inSource.close()
    outSource.close()
  }
}

@scala.annotation.tailrec
private def writeToFile(outSource: PrintWriter, contents: Seq[String]) {
  if (! contents.isEmpty) {
    outSource.println(contents.head)
    writeToFile(outSource, contents.tail)
  }
}

private def process(contents: Seq[String]) = contents.map(_.toUpperCase)

【问题讨论】:

  • 猜测:.getLines.toSeq?

标签: scala functional-programming iterator lazy-evaluation


【解决方案1】:

正如 fge 所暗示的,修改 process 以采用迭代器并删除 .toSeqinSource.getLines 已经是一个迭代器。

转换为Seq 将导致项目被记住。我认为它将迭代器转换为Stream 并导致所有项目都被记住。

编辑:好的,它更微妙。通过在过程结果上调用iterator,您正在执行与Iterator.toSeq.iterator 等效的操作。这可能会导致内存不足异常。

scala> Iterator.continually(1).toSeq.iterator.take(300*1024*1024).size
java.lang.OutOfMemoryError: Java heap space

这可能与此处报告的问题相同:https://issues.scala-lang.org/browse/SI-4835。请注意我在错误末尾的评论,这是来自个人经验。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-08
    • 2012-12-11
    • 2013-01-21
    • 2010-10-11
    • 1970-01-01
    • 1970-01-01
    • 2012-03-08
    • 2013-04-27
    相关资源
    最近更新 更多