Il problema di prestazioni non ha nulla a che fare con il modo in cui i dati vengono letti. È già bufferizzato. Non succede nulla fino a quando effettivamente iterazioni sulle linee:
// 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
Considerando una lettura velocità di 500MB al secondo per il mio disco rigido, il tempo ottimale sarebbe a 400ms per la 200mb, il che significa che non c'è spazio per miglioramenti diversi da non convertire l'iteratore in un array.
A seconda dell'applicazione, è possibile utilizzare direttamente l'iteratore anziché una matrice. Perché lavorare con un array così grande in memoria sarà comunque un problema di prestazioni.
Edit: Dai vostri commenti suppongo, che si desidera trasformare ulteriormente l'array (forse dividere le righe in colonne come hai detto che si sta leggendo un array numerico). In tal caso, consiglio di effettuare la trasformazione durante la lettura. Per esempio:
source.getLines.map(_.split(",").map(_.trim.toInt)).toArray
è notevolmente più veloce rispetto
source.getLines.toArray.map(_.split(",").map(_.trim.toInt))
(Per me è 1.9s invece di 2.5s) perché non trasformare un intero array gigante in un altro, ma solo ogni riga individualmente, finendo in un unico array (utilizza solo metà dello spazio heap). Inoltre, dal momento che la lettura del file è un collo di bottiglia, la trasformazione durante la lettura ha il vantaggio che ciò comporta un migliore utilizzo della CPU.
fonte
2014-04-28 16:07:57
Nota che 'Source' usa' BufferedSource', che a sua volta usa 'BufferedReader' di Java. Quindi legge già blocchi di dati in memoria - non legge byte per byte. – DNA
@DNA molte grazie per l'osservazione, chiedendo se ci sono (anche) approcci più veloci, forse con java.nio ... – elm
per favore, definire * file molto grandi * e cosa farai con quei dati (dopo la divisione in righe) –