在我的机器上,3.8 GHz i7 和 SSD
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.8 GHz i7 上打印。
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 的空间来做到这一点?
这不使用少于 1 KB 的堆。如果您查看在此调用之前和之后使用了多少内存,您通常会发现根本没有增加。
另一件事,这是否提供了有效的加载也意味着 MappedByteBuffer?
根据我的经验,使用内存映射文件是迄今为止最快的,因为您减少了系统调用和复制到内存的次数。
因为,在一些文章中我发现 read(buffer) 这提供了更好的加载性能。(我检查了一个,真正更快的 2.2 亿 int 数组 -float 数组读取 5 秒)
我想读那篇文章,因为我从未见过。
另一个问题:readLong 在读取代码输出文件时出错
证明的部分性能是以本机字节顺序存储值。writeLong/readLong 总是使用大端格式,这在英特尔/AMD 系统上要慢得多,这些系统本身就是小端格式。
您可以将字节顺序设为大端,这会减慢速度,或者您可以使用本机排序(DataInput/OutputStream 仅支持大端)