I'm trying to understand if the performance i'm obtaining from the get() method of the MappedByteBuffer class is normal or not. My code is the following:
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();
Since i'm a beginner, and i needed the fastest way to read data from SD card, i looked for documentation and i found that File Mapping is considered, in many cases, the fastest approach to read from a file. But if i run the above code, although the buffer is correctly filled, the performance is so slow (or maybe not ? You decide !!) that i can read those 4194304 bytes in almost 5 seconds, that's less than 1MB per second. I'm using Eclipse directly connected to my Optimus Dual smartphone; the same time is required for the read even if i put the reading operation in a loop (maybe overhead initialization wouldn't take place if multiple reads are performed...Not the case).
This file size-time relation doesn't change if i reduce or make the file larger: 8 megs will be read in almost 9 seconds, 2 megs in 2 seconds, and so on. I've read that even a slow SD card can be read at a speed of at least 5 MB per second... Note that 4194304 is a power of 2 value, since i've read that this would increase performance. Please tell me your opinion: is 1MB per second the actual performance on a modern smartphone, or is there something wrong with my code ? Thank you
Its worth nothing that in the Hotspot JVM, MappedByteBuffer.get() uses an intrinsic rather than a native call. When copying large sections blocks of data it copies multiple bytes at a time e.g. 8 bytes or longer with MMX instructions.
AFAIK, Android doesn't do this, which makes this call much more expensive.
I can't see anything wrong with your code. It is probably just the speed of the device and / or the file system implementation. As Tom Hawtin puts it "[m]emory mapped I/O will not make your disks run faster".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With