私は、バイナリファイル(最大50メガ)から膨大な数の整数を処理するアプリケーションを作成中です。私はできるだけ早くそれを行う必要があり、主なパフォーマンスの問題はディスクアクセス時間です。ディスクから多数の読み取りを行うため、読み取り時間を最適化すると、一般的にアプリのパフォーマンスが向上します。
これまで、ファイルを分割するブロックが少ないほど(つまり、読み取りが少ない/読み取りサイズが大きい)、アプリの動作が速くなると考えていました。これは、HDDがその機械的性質のために、ブロックの先頭を見つけるのが非常に遅いためです。ただし、読み取りを要求したブロックの先頭が見つかると、実際の読み取りをかなり迅速に実行する必要があります。
まあ、それは私がこのテストを実行するまででした:
古いテストが削除され、HDDキャッシングが原因で問題が発生しました
新しいテスト(ファイルが大きすぎて(1GB)、ファイル内のランダムな場所にアクセスするため、HDDキャッシュはここでは役に立ちません):
int mega = 1024 * 1024;
int giga = 1024 * 1024 * 1024;
byte[] bigBlock = new byte[mega];
int hundredKilo = mega / 10;
byte[][] smallBlocks = new byte[10][hundredKilo];
String location = "C:\\Users\\Vladimir\\Downloads\\boom.avi";
RandomAccessFile raf;
FileInputStream f;
long start;
long end;
int position;
java.util.Random rand = new java.util.Random();
int bigBufferTotalReadTime = 0;
int smallBufferTotalReadTime = 0;
for (int j = 0; j < 100; j++)
{
position = rand.nextInt(giga);
raf = new RandomAccessFile(location, "r");
raf.seek((long) position);
f = new FileInputStream(raf.getFD());
start = System.currentTimeMillis();
f.read(bigBlock);
end = System.currentTimeMillis();
bigBufferTotalReadTime += end - start;
f.close();
}
for (int j = 0; j < 100; j++)
{
position = rand.nextInt(giga);
raf = new RandomAccessFile(location, "r");
raf.seek((long) position);
f = new FileInputStream(raf.getFD());
start = System.currentTimeMillis();
for (int i = 0; i < 10; i++)
{
f.read(smallBlocks[i]);
}
end = System.currentTimeMillis();
smallBufferTotalReadTime += end - start;
f.close();
}
System.out.println("Average performance of small buffer: " + (smallBufferTotalReadTime / 100));
System.out.println("Average performance of big buffer: " + (bigBufferTotalReadTime / 100));
結果:小さなバッファーの平均-35ms大きなバッファーの平均-40ms?!(LinuxとWindowsで試してみましたが、どちらの場合もブロックサイズが大きいほど読み取り時間が長くなります。なぜですか?)
このテストを何度も実行した後、魔法の理由で、1つの大きなブロックを読み取ると、小さいサイズの10ブロックを順番に読み取るよりも平均して時間がかかることに気付きました。Windowsが賢すぎて、ファイルシステムで何かを最適化しようとした結果かもしれないと思ったので、Linuxで同じコードを実行しましたが、驚いたことに同じ結果が得られました。
なぜこれが起こっているのか私にはわかりません、誰かが私にヒントを教えてもらえますか?また、この場合の最適なブロックサイズは何ですか?
敬具