2014-04-11 2 views
9

에 업로드, 일반적인 접근 방식은 매우 큰 파일을스칼라 빠른 텍스트 파일 읽기 및 텍스트 파일을 읽고 배열로 업로드를 들어, 스칼라에서 메모리

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

특히입니다 빠른 방법은 아마도이 바이트 블록을 메모리에 먼저 읽은 다음 새 줄 문자로 나누면됩니까? (일반적으로 사용되는 방법은 Read entire file in Scala을 참조하십시오.)

많은 감사.

+2

'소스'는'BufferedSource'를 사용하는데, 이는 다시'BufferedReader'를 사용합니다. 따라서 이미 데이터 블록을 메모리로 읽습니다. 바이트 단위로 읽지는 않습니다. – DNA

+0

@DNA java.nio를 사용하여 (심지어) 더 빠른 접근법이 있는지 궁금해하는 관측에 많은 감사를드립니다 ... – elm

+1

* 매우 큰 파일 *을 정의하고 그 데이터로 무엇을 할 것인지 (분할 후 그 행은 다음과 같습니다. –

답변

19

성능 문제는 데이터를 읽는 방식과 관련이 없습니다. 이미 버퍼링되었습니다. 실제로 라인을 통해 반복 할 때까지 아무런 변화가 없습니다 :

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

내 하드 드라이브에 대한 초당 5백메가바이트의 읽기 속도를 고려, 최적의 시간의 여지가 없다는 것을 의미 200메가바이트에 대한 400ms 일에있을 것입니다 이터레이터를 배열로 변환하지 않는 것 이외의 개선 사항.

응용 프로그램에 따라 배열 대신 직접 이터레이터를 사용할 수 있습니다. 메모리에서 이러한 거대한 배열로 작업하는 것이 어쨌든 성능 문제가 될 것이기 때문입니다.


편집 : 난 당신이 더 배열을 변환하려는, 가정 귀하의 의견에서은 (당신이 숫자 배열을 읽고 말했듯이 아마 열에 라인을 분할). 이 경우 나는 읽는 동안 변형을하는 것이 좋습니다. 예를 들어 :

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

는 다른에 전체 거대한 배열을 변환하지 않기 때문에 (이 1.9s 대신 2.5s 나를 위해)

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

보다 상당히 빠르지 만 단지 각 라인 개별적으로 단일 배열로 끝납니다 (힙 공간의 절반 만 사용함). 또한 파일을 읽는 것이 병목이므로 판독하는 동안 변환하면 CPU 사용률이 향상됩니다.

+0

많은 분들께 감사드립니다. 그러나 문제는 파일을 메모리 단위로 업로드해야하며 파일 단위로 처리해야합니다. – elm

+0

좋은 답변입니다. –

+0

@ user3189923 일부 추가 정보는 내 편집을 참조하십시오 ... –