【问题标题】:Scala fast text file read and upload to memoryScala快速文本文件读取并上传到内存
【发布时间】:2014-05-25 07:36:42
【问题描述】:

在 Scala 中,为了读取文本文件并将其上传到数组中,一种常见的方法是

scala.io.Source.fromFile("file.txt").getLines.toArray

特别是对于非常大的文件,是否有更快的方法可能是先将字节块读入内存,然后用换行符分割它们? (常用方法见Read entire file in Scala。)

非常感谢。

【问题讨论】:

  • 请注意Source 使用BufferedSource,而后者又使用Java 的BufferedReader。所以它已经将数据块读入内存——它不会逐字节读取。
  • @DNA 非常感谢您的观察,想知道是否有(甚至)更快的方法,也许是 java.nio ...
  • 请定义非常大的文件以及您将要如何处理这些数据(将其分成几行之后)
  • @om-nom-nom 数值数组 20.000 x 500 ~ 200MB
  • 接下来,显而易见的问题是:您当前的方法有多快,以及有多快足够快

标签: file scala io scalaz scalaz-stream


【解决方案1】:

性能问题与读取数据的方式无关。它已经被缓冲了。在您实际遍历这些行之前,什么都不会发生:

// measures time taken by enclosed code
def timed[A](block: => A) = {
  val t0 = System.currentTimeMillis
  val result = block
  println("took " + (System.currentTimeMillis - t0) + "ms")
  result
}

val source = timed(scala.io.Source.fromFile("test.txt")) // 200mb, 500 lines
// took 0ms

val lines = timed(source.getLines)
// took 0ms

timed(lines.next) // read first line
// took 1ms

// ... reset source ...

var x = 0
timed(lines.foreach(ln => x += ln.length)) // "use" every line
// took 421ms

// ... reset source ...

timed(lines.toArray)
// took 915ms

考虑到我的硬盘读取速度为每秒 500mb,200mb 的最佳时间是 400ms,这意味着除了不将迭代器转换为数组之外,没有任何改进的余地。

根据您的应用程序,您可以考虑直接使用迭代器而不是数组。因为在内存中使用如此庞大的数组肯定会成为性能问题。


编辑:从您的 cmets 我假设您想要进一步转换数组(也许正如您所说的那样将行分成列,因为您正在读取数字数组)。在这种情况下,我建议在阅读时进行转换。例如:

source.getLines.map(_.split(",").map(_.trim.toInt)).toArray

快很多
source.getLines.toArray.map(_.split(",").map(_.trim.toInt))

(对我来说是 1.9 秒而不是 2.5 秒) 因为您不会将整个巨型数组转换为另一个,而只是将每一行单独转换为一个数组(仅使用一半的堆空间)。此外,由于读取文件是一个瓶颈,因此在读取时进行转换的好处是可以提高 CPU 利用率。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-02
    • 1970-01-01
    • 1970-01-01
    • 2013-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多