6

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 カードからデータを読み取る最速の方法が必要だったので、ドキュメントを探したところ、多くの場合、ファイル マッピングがファイルから読み取る最速の方法であると考えられていることがわかりました。しかし、上記のコードを実行すると、バッファーは正しく満たされていますが、パフォーマンスが非常に遅い (または、そうでない場合もあります !!) ため、これらの 4194304 バイトをほぼ 5 秒で読み取ることができます。つまり、 1 秒あたり 1MB 未満です。Optimus Dual スマートフォンに直接接続された Eclipse を使用しています。読み取り操作をループに入れたとしても、読み取りには同じ時間が必要です(複数の読み取りが実行されると、オーバーヘッドの初期化が行われない可能性があります...そうではありません)。

このファイル サイズと時間の関係は、ファイルを小さくしたり大きくしたりしても変わりません。8 MB はほぼ 9 秒で読み取られ、2 MB は 2 秒で読み取られます。遅いSDカードでも毎秒5 MB以上の速度で読み取ることができると読みました... 4194304は2の累乗値であることに注意してください。これによりパフォーマンスが向上すると読んだためです。あなたの意見を教えてください: 毎秒 1MB は最新のスマートフォンでの実際のパフォーマンスですか、それとも私のコードに何か問題がありますか? ありがとうございました

4

2 に答える 2

3

Hotspot JVM では、 MappedByteBuffer.get() がネイティブ呼び出しではなく組み込み呼び出しを使用することに何の価値もありません。データの大きなセクション ブロックをコピーする場合、一度に複数のバイトをコピーします。たとえば、MMX 命令では 8 バイト以上をコピーします。

私の知る限り、Androidはこれを行わないため、この呼び出しははるかに高価になります.

于 2012-11-20T13:07:06.223 に答える
1

あなたのコードに問題はありません。おそらく、デバイスの速度および/またはファイルシステムの実装です。Tom Hawtinが言うように、「[m]メモリ マップド I/O はディスクの実行速度を向上させません」。

于 2012-11-20T13:02:39.090 に答える