私のマシンでは、SSDを搭載した3.8 GHzi7
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("abc.txt"), 32 * 1024));
long start = System.nanoTime();
final int count = 220000000;
for (int i = 0; i < count; i++) {
long l = i;
dos.writeLong(l);
}
dos.close();
long time = System.nanoTime() - start;
System.out.printf("Took %.3f seconds to write %,d longs%n",
time / 1e9, count);
プリント
Took 11.706 seconds to write 220,000,000 longs
メモリマップトファイルの使用
final int count = 220000000;
final FileChannel channel = new RandomAccessFile("abc.txt", "rw").getChannel();
MappedByteBuffer mbb = channel.map(FileChannel.MapMode.READ_WRITE, 0, count * 8);
mbb.order(ByteOrder.nativeOrder());
long start = System.nanoTime();
for (int i = 0; i < count; i++) {
long l = i;
mbb.putLong(l);
}
channel.close();
long time = System.nanoTime() - start;
System.out.printf("Took %.3f seconds to write %,d longs%n",
time / 1e9, count);
// Only works on Sun/HotSpot/OpenJDK to deallocate buffer.
((DirectBuffer) mbb).cleaner().clean();
final FileChannel channel2 = new RandomAccessFile("abc.txt", "r").getChannel();
MappedByteBuffer mbb2 = channel2.map(FileChannel.MapMode.READ_ONLY, 0, channel2.size());
mbb2.order(ByteOrder.nativeOrder());
assert mbb2.remaining() == count * 8;
long start2 = System.nanoTime();
for (int i = 0; i < count; i++) {
long l = mbb2.getLong();
if (i != l)
throw new AssertionError("Expected "+i+" but got "+l);
}
channel.close();
long time2 = System.nanoTime() - start2;
System.out.printf("Took %.3f seconds to read %,d longs%n",
time2 / 1e9, count);
// Only works on Sun/HotSpot/OpenJDK to deallocate buffer.
((DirectBuffer) mbb2).cleaner().clean();
3.8GHzi7で印刷します。
Took 0.568 seconds to write 220,000,000 longs
遅いマシンでの印刷
Took 1.180 seconds to write 220,000,000 longs
Took 0.990 seconds to read 220,000,000 longs
これを作成しない他の方法はありますか?そのアレイはすでにメインメモリにあり、500 MBを超える容量を割り当てることができないためですか?
これは、1KB未満のヒープを使用しません。この呼び出しの前後に使用されているメモリの量を見ると、通常はまったく増加していません。
もう1つ、これにより効率的な読み込みが可能になり、MappedByteBufferも意味しますか?
私の経験では、システムコールとメモリへのコピーの数を減らすため、メモリマップトファイルを使用するのがはるかに高速です。
なぜなら、いくつかの記事でread(buffer)を見つけたので、これにより読み込みパフォーマンスが向上します。(私は、1つ、本当に速い2億2000万のint配列-float配列が5秒を読み取ることを確認します)
私はそれを見たことがないので、その記事を読みたいと思います。
別の問題:コード出力ファイルからの読み取り中にreadLongでエラーが発生する
証明のパフォーマンスの一部は、ネイティブバイトオーダーで値を格納することです。writeLong / readLongは常にビッグエンディアン形式を使用しますが、ネイティブのリトルエンディアン形式であるIntel/AMDシステムでははるかに低速です。
バイトオーダーをビッグエンディアンにして速度を落とすか、ネイティブオーダーを使用できます(DataInput / OutputStreamはビッグエンディアンのみをサポートします)