【发布时间】:2012-11-20 12:42:34
【问题描述】:
我试图了解我从 MappedByteBuffer 类的 get() 方法获得的性能是否正常。我的代码如下:
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();
由于我是初学者,并且我需要从 SD 卡读取数据的最快方法,因此我查找了文档,发现文件映射在许多情况下被认为是从文件中读取数据的最快方法。但是如果我运行上面的代码,虽然缓冲区被正确填充,但性能太慢了(或者可能不是?你决定!!)我可以在 几乎 5 秒内读取那些 4194304 字节,那就是每秒小于 1MB。我正在使用 Eclipse 直接连接到我的 Optimus Dual 智能手机;即使我将读取操作置于循环中,读取也需要相同的时间(如果执行多次读取,可能不会发生开销初始化......不是这种情况)。
如果我减小或增大文件,这个文件大小与时间的关系不会改变:8 兆将在 9 秒内读取,2 兆将在 2 秒内读取,依此类推。 我读过,即使是慢速 SD 卡也可以以每秒至少 5 MB 的速度读取...... 请注意,4194304 是 2 值的幂,因为我已经读过这会提高性能。 请告诉我您的意见:现代智能手机的实际性能是每秒 1MB,还是我的代码有问题?谢谢
【问题讨论】:
-
如果使用以下命令读取性能会更好:while(mappedByteBuffer.hasRemaining()) { mappedByteBuffer.get()); }; ?
-
如果您需要对文件进行随机读/写访问,则内存映射文件是有意义的。如果您只需要在我使用普通的旧 Java io(可能是 nio 通道)后将数据读入内存。在有内存限制的移动平台上将 4 或 8MB 的文件读入内存也不是一个好主意。除此之外,我倾向于说有问题。 SD 卡(除非非常便宜)应该能够读取至少 2MB/s(2 级,仍然很便宜),手机内部存储应该更像 20MB/s。如果您想确保它不仅仅是硬件限制,请尝试使用不同的实现
-
你有没有尝试过其他方法,看看能不能得到更好的表现?
-
@zapl :感谢您的提示,这实际上只是一个测试。在实际代码中,我将使用 512KB 左右的缓冲区。注意:我刚刚尝试过普通的 nio 通道,并且性能有所提高(??),现在我可以在一秒钟内读取近 2 兆字节。不完美,但确实更好!
-
@AndrzejDoyle:我做了那个测试,但并不走运,从/到 PC(通过 USB 连接到智能手机)的复制几乎是立即使用用于测试的 4 megs 文件完成的。所以,这不是硬件问题...
标签: java android performance file mapping