Быстрый текстовый файл Scala считывается и загружается в память
в Scala для чтения текстового файла и загрузки его в массив общим подходом является
scala.io.Source.fromFile("file.txt").getLines.toArray
особенно для очень больших файлов, есть ли более быстрый подход, возможно, сначала читая блоки байтов в память, а затем разделяя их на новые символы строки ? (См.читать весь файл в Scala для часто используемых подходов.)
Большое Спасибо.
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
учитывая скорость чтения 500 Мб в секунду для моего жесткого диска, оптимальное время будет на 400 мс для 200 Мб, что означает, что нет места для улучшений, кроме как не преобразования итератора в массив.
В зависимости от вашего приложения вы можете рассмотреть возможность использования итератора непосредственно вместо массива. Потому что работа с таким огромным массивом в памяти, безусловно, будет проблемой производительности в любом случае.
редактировать: из ваших комментариев я предполагаю, что вы хотите дополнительно преобразовать массив (возможно, разделить строки на столбцы, как вы сказали, что читаете числовой массив). В этом случае я рекомендую сделать трансформацию во время чтения. Например:
source.getLines.map(_.split(",").map(_.trim.toInt)).toArray
- это значительно быстрее, чем
source.getLines.toArray.map(_.split(",").map(_.trim.toInt))
(для мне это 1.9 s вместо 2.5 s) потому что вы не преобразуете весь гигантский массив в другой, а только каждую строку отдельно, заканчивая одним массивом (использует только половину пространства кучи). Кроме того, поскольку чтение файла является узким местом, преобразование при чтении имеет то преимущество, что оно приводит к лучшему использованию ЦП.