【问题标题】:JAVA using RandomAccessFile after seek is very slow. What is the reason?查找后使用 RandomAccessFile 的 JAVA 非常慢。是什么原因?
【发布时间】:2018-05-05 15:24:54
【问题描述】:

这是我的测试代码

long fileSize = 1024 * 1024 * 512L;
byte[] bts = new byte[8];

RandomAccessFile randomAccessFile = new RandomAccessFile("f:/test.data", "rw");
randomAccessFile.setLength(fileSize);

randomAccessFile.seek(0);
long time = System.nanoTime();
randomAccessFile.write(bts);
System.out.println("write1 use:" + (System.nanoTime() - time));

randomAccessFile.seek(1024 * 1024 * 256L);
time = System.nanoTime();
randomAccessFile.write(bts);
System.out.println("write2 use:" + (System.nanoTime() - time));

打印

write1 use:181051
write2 use:2029338072

可以看出,两次写入是9字节,第二次比第一次慢10000倍。

所以想问一下为什么seek会导致文件写得这么慢。有什么解决办法吗?

【问题讨论】:

  • 第二次搜索时,由于偏移量很大,这必须创建约 256MB 的数据。你为什么要追求这么远?
  • 我正在开发一个高速http下载器,需要同时下载多个块,所以我想在块向下响应时搜索文件。
  • 用较小的偏移量进行测试,看看延迟是否成比例。或者,先写出分块文件,然后再组装。
  • 您的操作系统和文件系统类型是什么?为了使这样的事情能够正常工作并且不会非常慢,操作系统和文件系统必须支持sparse files。否则,当您写入一个较大的偏移量且两者之间没有先前的数据时,系统需要按照@tadman 在他的评论中所述创建所有数据。另请注意,您可以使用FileChannel.write(ByteBuffer src, long position) 写入文件中的任意位置而无需查找。
  • 非常感谢。我尝试将 Files.newByteChannel() 与 StandardOpenOption.SPARSE 选项一起使用。它非常快

标签: java performance io seek randomaccessfile


【解决方案1】:

你想要的是创建一个稀疏文件。 https://en.wikipedia.org/wiki/Sparse_file

final ByteBuffer buf = ByteBuffer.allocate(4).putInt(2);
buf.rewind();

final OpenOption[] options = {
    StandardOpenOption.WRITE,
    StandardOpenOption.CREATE_NEW,
    StandardOpenOption.SPARSE
};
final Path path = Paths.get("/tmp/foo");
Files.deleteIfExists(path);

try (
    final SeekableByteChannel channel
        = Files.newByteChannel(path, options);
) {
    channel.position(1L << 31);
    channel.write(buf);
}

代码取自What is the use of StandardOpenOption.SPARSE?

【讨论】:

    猜你喜欢
    • 2018-05-08
    • 2010-10-31
    • 1970-01-01
    • 2010-09-22
    • 1970-01-01
    • 2015-08-31
    • 1970-01-01
    • 1970-01-01
    • 2015-08-01
    相关资源
    最近更新 更多