Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么nio.files.copy比nio.fileChannel copy慢得多?_Java_Performance_Copy_Nio_Jmh - Fatal编程技术网

Java 为什么nio.files.copy比nio.fileChannel copy慢得多?

Java 为什么nio.files.copy比nio.fileChannel copy慢得多?,java,performance,copy,nio,jmh,Java,Performance,Copy,Nio,Jmh,我是Java程序员初学者。 今天,我练习了如何用java复制文件,并尝试学习本教程 完成本教程后,我使用57MB的txt文件运行JMH基准测试以检查性能。 nioFiles和NIOChannel之间的性能差距比我预期的要大。 Benchmark Mode Cnt Score Error Units CompressTest.fileCopyUsingNIOChannelClass thrpt 10 22.4

我是Java程序员初学者。
今天,我练习了如何用java复制文件,并尝试学习本教程
完成本教程后,我使用57MB的txt文件运行JMH基准测试以检查性能。
nioFiles和NIOChannel之间的性能差距比我预期的要大。

Benchmark                                   Mode  Cnt   Score   Error  Units
CompressTest.fileCopyUsingNIOChannelClass  thrpt   10  22.465 ± 2.996  ops/s
CompressTest.fileCopyWithNIOFiles          thrpt   10   0.843 ± 0.488  ops/s
以下是我使用的代码

    @Warmup(iterations = 5, time = 1000, timeUnit = TimeUnit.MILLISECONDS)
    @Measurement(iterations = 10, time = 1000, timeUnit = TimeUnit.MILLISECONDS)
    @Fork(1)
    @State(Scope.Benchmark)
    public class CompressTest
    {
    final static Path source = Paths.get("c:/temp/system.out.lambda.txt");
    final static Path target = Paths.get("c:/temp/copied.lambda.txt");

    public static void main(String[] args) throws RunnerException, IOException {
        Main.main(args);
    }

    @Benchmark
    public static void fileCopyWithNIOFiles() throws IOException{
        Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
    }
    @Benchmark
    public static void fileCopyUsingNIOChannelClass() throws IOException
        {
            File fileToCopy = new File("c:/temp/system.out.lambda.txt");
            FileInputStream inputStream = new FileInputStream(fileToCopy);
            FileChannel inChannel = inputStream.getChannel();

            File newFile = new File("c:/temp/testcopied.txt");
            FileOutputStream outputStream = new FileOutputStream(newFile);
            FileChannel outChannel = outputStream.getChannel();

            inChannel.transferTo(0, fileToCopy.length(), outChannel);
            inputStream.close();
            outputStream.close();
        }
}
所以我想问,我做错什么了吗?或者你能解释一下为什么会这样吗


有人问了,所以我试着看了另一份文件。348MB avi文件,以下是结果

Benchmark                                   Mode  Cnt  Score   Error  Units
CompressTest.fileCopyUsingNIOChannelClass  thrpt   10  3.142 ± 0.738  ops/s
CompressTest.fileCopyWithNIOFiles          thrpt   10  1.991 ± 0.350  ops/s
使用nioFile进行静态文件复制比使用NIOChannel慢


我刷新了所有内容并再次测试了一次,这就是reuslt。使用57MB txt文件,并将预热迭代次数设置为10

Benchmark                                   Mode  Cnt   Score   Error  Units
CompressTest.fileCopyUsingNIOChannelClass  thrpt   10  23.442 ± 3.224  ops/s
CompressTest.fileCopyWithNIOFiles          thrpt   10  12.328 ± 2.128  ops/s
这个结果比第一个结果更容易接受,但NIO文件复制的速度几乎是NIO通道的一半

附言:如果有更好的方法复制文件,请告诉我。我真的很想了解更多关于java的知识,谢谢

TL;DR-这就是缓存问题

在任务管理器中运行基准打开性能选项卡时,您将看到差异的来源

文件.copy测试期间,您可能会看到磁盘写入速度很快。但是当
transferTo
test运行时,磁盘将几乎处于空闲状态!这意味着实际上没有数据写入设备-复制是在内存中执行的。这显然要快得多

Java
Files.copy
方法是使用WinAPI函数实现的。没有明确的规范说明
CopyFileEx
如何在内部工作,但可以观察到它执行一些实际的磁盘I/O


反过来,
transferTo
执行一系列的
ReadFile
/
WriteFile
调用。函数不能保证数据立即写入磁盘。它可能会将数据放在操作系统磁盘缓存中,并在以后的某个时候在后台执行真正的设备I/O。

在阅读了@apangin的解释后,我在Windows中运行了资源监视器,下面的img是帮助我理解的结果。谢谢大家。

我用你的方法得到了相反的结果。我使用22MB的PDF文件进行了测试,fileCopyWithNIOFiles()方法比fileCopyUsingNIOChannelClass()快约15倍。您也可以尝试不同的文件吗?@user3301492谢谢您的建议。我也尝试了另一个文件,并添加了新的基准测试结果。您在每次复制操作中都复制同一个文件。操作系统缓存文件内容,所以无论哪种方法首先执行,几乎总是会比较慢,至少在您第一次运行程序时是这样。@VGR但是在JMH基准测试中,在真正的迭代之前有一个预热迭代,所以我认为在这种情况下这不会是一个问题。谢谢!我在windows7中使用了资源监视器,终于找到了区别的来源。