2012-11-20 2 views
6

Sto cercando di capire se la prestazione che sto ottenendo dal metodo get() della classe MappedByteBuffer è normale o meno. Il mio codice è il seguente:Java MappedByteBuffer.get() sorprendentemente lento

private byte[] testBuffer = new byte[4194304]; 
private File sdcardDir, filepath; 
private FileInputStream inputStream; 
private FileChannel fileChannel; 
private MappedByteBuffer mappedByteBuffer; 

// Obtain the root folder of the external storage 
sdcardDir = Environment.getExternalStorageDirectory(); 

// Create the reference to the file to be read 
filepath = new File(sdcardDir, "largetest.avi"); 
inputStream = new FileInputStream(filepath); 
fileChannel = inputStream.getChannel(); 

mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, (4194304)); 

Log.d("GFXUnpack", "Starting to read"); 
mappedByteBuffer.position(0); 
mappedByteBuffer.get(testBuffer, 0, (4194304)); 
Log.d("GFXUnpack", "Ended to read"); 
mappedByteBuffer.rewind(); 

Dal momento che sono un principiante, e avevo bisogno il modo più veloce per leggere i dati dalla scheda SD, ho guardato per la documentazione e ho trovato che la mappatura del file è considerato, in molti casi, l'approccio più veloce per leggere da un file. Ma se eseguo il codice sopra, anche se il buffer è riempito correttamente, le prestazioni sono così lente (o forse no? Decidi !!) che posso leggere quei 4194304 byte in quasi 5 secondi, ovvero meno di 1 MB per secondo. Uso Eclipse direttamente collegato al mio smartphone Optimus Dual; lo stesso tempo è richiesto per la lettura anche se inserisco l'operazione di lettura in un ciclo (forse l'inizializzazione del sovraccarico non avverrebbe se vengono eseguite letture multiple ... Non è il caso).

Questa relazione dimensione-tempo del file non cambia se riduco o ingrandisco il file: 8 mega saranno letti in quasi 9 secondi, 2 mega in 2 secondi e così via. Ho letto che anche una scheda SD lenta può essere letta ad una velocità di almeno 5 MB al secondo ... Nota che 4194304 è una potenza di 2 valore, poiché ho letto che questo aumenterebbe le prestazioni. Per favore dimmi la tua opinione: è 1MB al secondo le prestazioni effettive su uno smartphone moderno, o c'è qualcosa di sbagliato nel mio codice? Grazie

+0

La prestazione è migliore se si legge con: while (mappedByteBuffer.hasRemaining()) { mappedByteBuffer.get()); }; ? –

+1

I file di memoria mappati hanno senso se è necessario un accesso in lettura/scrittura casuale ai file. Se hai solo bisogno di leggere i dati in memoria una volta che userò il semplice vecchio io io (forse i canali nio). Inoltre, non è una buona idea leggere un file di 4 o 8 MB in memoria su una piattaforma mobile con limitazioni di memoria. A parte questo, tendo a dire che c'è qualcosa di sbagliato. Le schede SD (a meno che non siano molto economiche) dovrebbero essere in grado di leggere almeno 2 MB/s (classe 2, ancora piuttosto economica) e la memoria interna del telefono dovrebbe essere più simile a 20 MB/s. Provalo con un'implementazione diversa se vuoi essere sicuro che non sia solo il limite hardware – zapl

+0

hai provato un altro metodo per vedere se puoi ottenere prestazioni migliori? – njzk2

risposta

1

Non riesco a vedere nulla di sbagliato con il tuo codice. Probabilmente è solo la velocità del dispositivo e/o dell'implementazione del file system. Come dice Tom Hawtin "I/O mappato [m] emory non renderanno i tuoi dischi più veloci".

+0

Dopo tutto, stiamo parlando di una quantità minima di istruzioni, penso che non potrebbe essere più ottimizzato. Ho provato a estrarre quelle istruzioni dal progetto originale - che includeva multithreading e lock/sblocchi - e le ho inserite in un progetto quasi vuoto, ma ho avuto gli stessi orari di lettura – Logicat

3

Non vale nulla che nella JVM Hotspot, MappedByteBuffer.get() utilizza una chiamata intrinseca piuttosto che nativa. Quando si copiano blocchi di dati di sezioni grandi, copia più byte alla volta, ad es. 8 byte o più con le istruzioni MMX.

AFAIK, Android non esegue questa operazione, il che rende questa chiamata molto più costosa.

+0

Mentre non dubito che quello che dici sia vero , questo non spiega perché il tasso di lettura è basso come osserva l'OP. Per lo meno, non può essere l'intera risposta. –

+1

Per testare le prestazioni dell'hardware è possibile provare a copiare il file sul telefono o da/verso un PC (non in Java) –