天下无110 2023-01-09 11:17 采纳率: 0%
浏览 31

java,transferTo速度慢与RandomAccessFile

为什么transferTo(也就是sendfile 零拷贝)要比RandomAccessFile(随机写)要慢?

今天做了一个复制大文件的测试,分别使用transferTo和RandomAccessFile复制4G大小的文件,原本以为使用transferTo这种0拷贝的应该是最快的,但是实验发现使用RandomAccessFile加ByteBuffer的这种却是比较快的。
这里就产生问题,ByteBuffer这种一定又用户空间和内核空间的转换消耗。而transferTo理论上是没有这部分消耗,但是为什么确是RandomAccessFile这种方式快那??
求高人解析下
代码如下 test1是transferTo ,test2是RandomAccessFile

public class Test {
    public static void main(String[] args) throws IOException {
        long start = System.currentTimeMillis();
        test1();
        System.out.println("time1:" + (System.currentTimeMillis() - start));

        long start2 = System.currentTimeMillis();
        test2();
        System.out.println("time2:" + (System.currentTimeMillis() - start2));
    }

    public static void test1() throws IOException {
        // FileUtils.copyFile(new File("D:\\iso\\CentOS-7-x86_64-DVD-2009.iso"), new File("D:\\iso\\CentOS-7-x86_64-DVD-2009.iso3"));

        File sourceFile = new File("D:\\iso\\CentOS-7-x86_64-DVD-2009.iso");
        FileInputStream fis = new FileInputStream(sourceFile);
        FileChannel fisChannel = fis.getChannel();

        FileOutputStream fos = new FileOutputStream("D:\\iso\\CentOS-7-x86_64-DVD-2009.iso2");
        FileChannel fosChannel = fos.getChannel();
        //将fisChannel通道的数据,写入到fosChannel通道
        long size = fisChannel.size();
        long cpSize = 0;
        do {
            fisChannel.transferTo(cpSize, size - cpSize, fosChannel);
            cpSize = fosChannel.size();
            System.out.println(cpSize);
        } while (cpSize < size);
        // fosChannel.transferFrom(fisChannel,0,size);
        // fisChannel.transferTo(0, fisChannel.size(), fosChannel);

        System.out.println(fosChannel.size());
        fis.close();
        fos.flush();
        fos.close();

    }

    public static void test2() throws IOException {
        RandomAccessFile randomAccessFile1 = new RandomAccessFile("D:\\iso\\CentOS-7-x86_64-DVD-2009.iso", "r");
        RandomAccessFile randomAccessFile2 = new RandomAccessFile("D:\\iso\\CentOS-7-x86_64-DVD-2009.iso3", "rw");
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024 * 1024);
        while (true) {
            byteBuffer.clear();
            int read = randomAccessFile1.getChannel().read(byteBuffer);
            if (read == -1) {
                break;
            }
            byteBuffer.flip();
            randomAccessFile2.getChannel().write(byteBuffer);
        }
        randomAccessFile1.close();
        randomAccessFile2.close();
    }
}
  • 写回答

1条回答 默认 最新

  • 天寒雨落 全栈领域新星创作者 2023-01-09 12:01
    关注

    两种可能的原因:1.文件系统的不同。某些文件系统(如 NTFS)支持零拷贝技术,而其他文件系统(如 ext3)则不支持。如果使用的是不支持零拷贝技术的文件系统,那么 transferTo 方法的性能就会比使用 RandomAccessFile 进行随机写要慢。

    2.设备的不同。在某些情况下,transferTo 方法的性能可能受到磁盘或网络设备的限制。如果使用的是性能较差的设备,那么 transferTo 方法的性能也可能比使用 RandomAccessFile 进行随机写要慢。

    评论

报告相同问题?

问题事件

  • 创建了问题 1月9日

悬赏问题

  • ¥60 如何批量获取json的url
  • ¥15 对法兰连接元件所承受的表面载荷等效转化为法兰开孔接触面上的等效表面载荷?
  • ¥15 comsol仿真压阻传感器
  • ¥15 Python线性规划函数optimize.linprog求解为整数
  • ¥15 llama3中文版微调
  • ¥15 pg数据库导入数据序列重复
  • ¥15 三分类机器学习模型可视化分析
  • ¥15 本地测试网站127.0.0.1 已拒绝连接,如何解决?(标签-ubuntu)
  • ¥50 Qt在release捕获异常并跟踪堆栈(有Demo,跑一下环境再回答)
  • ¥30 python,LLM 文本提炼