java - 尝试比较 lib 的性能以将 InputStream 复制到 OutputStream

标签 java java-8

我想比较 Guava 和 Apache commons IO 将 InputStream 复制到 OutputStream:

我比较了(2 个线程同时启动,使用 CyclicBarrier)的速度:

  • org.apache.commons.io.IOUtils.copy
  • com.google.common.io.ByteStreams.copy

在 4Go 大小的文件上,结果完全一样,这里是我的问题,我不明白这怎么可能,除非背后的代码完全相同或其他原因,但老实说我认为我的测试课有问题吗?

结果

all threads started
commonsIo perf:PT6M21.281S
Guava perf:PT6M21.282S

代码:

public class Test {
    public static void main(String... a) throws InterruptedException, BrokenBarrierException {
        final CyclicBarrier gate = new CyclicBarrier(3);

        Thread t1 = new Thread() {
            public void run() {
                try {
                    gate.await();
                    Instant start = Instant.now();
                    IOUtils.copy(Files.newInputStream(Paths.get("C:\\Users\\emil.brigand\\Downloads\\CentOS-6.4-x86_64-bin-DVD1.iso")), Files.newOutputStream(Paths.get("C:\\Users\\emil.brigand\\Downloads\\CentOS-6.4-x86_64-bin-DVD12.iso"), StandardOpenOption.CREATE_NEW, StandardOpenOption.DELETE_ON_CLOSE));
                    Instant end = Instant.now();
                    System.out.println("commonsIo perf:" + Duration.between(start, end));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        };
        Thread t2 = new Thread() {
            public void run() {
                try {
                    gate.await();
                    Instant start = Instant.now();
                    ByteStreams.copy(Files.newInputStream(Paths.get("C:\\Users\\emil.brigand\\Downloads\\CentOS-6.4-x86_64-bin-DVD1.iso")), Files.newOutputStream(Paths.get("C:\\Users\\emil.brigand\\Downloads\\CentOS-6.4-x86_64-bin-DVD11.iso"), StandardOpenOption.CREATE_NEW, StandardOpenOption.DELETE_ON_CLOSE));
                    Instant end = Instant.now();
                    System.out.println("Guava perf:" + Duration.between(start, end));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        };
        t1.start();
        t2.start();
        gate.await();
        System.out.println("all threads started");
    }
}

最佳答案

你的基准不是很详细,你可以考虑在“How do I write a correct micro-benchmark in Java?”中找到的信息有关详细信息,但在这种情况下,这无关紧要。

当复制这么大的文件时,确实没有相关的性能差异,因为 I/O 速度将超过它。此外,在这两种情况下,使用 InputStream 进行文件复制操作的效率同样低下。

这意味着必须将数据从 I/O 缓冲区复制到 Java 字节数组中,然后再复制回来。从 Java 1.4 开始,有一个替代方案,FileChannel.transferTo它告诉底层系统直接传输字节而不复制到 Java 字节数组。

但由于您使用的是 PathFiles,您至少使用 Java 7,因此可以简单地使用 Files.copy(Path,Path,…)无需使用任何第三方库,也无需绕过 InputStream/OutputStream API。当然,它会利用NIO API的直接复制能力。

但有可能即使使用此 API,耗时也不会改变,因为如前所述,I/O 速度比这一切都重要。你不能通过重新排列程序代码来使硬盘驱动器等更快。与 CPU 速度相比,该硬件速度非常慢,允许 CPU 弥补软件中的许多低效率(如果有的话)。

不过,Files.copy 更易于使用,并且消除了对第 3 方库的依赖性,因此比较这些第 3 方库的性能没有意义......

关于java - 尝试比较 lib 的性能以将 InputStream 复制到 OutputStream,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32497065/

相关文章:

Java正则表达式数学测试

java - eclipse luna 不支持 glassfish?

lambda - 在使用lambda表达式进行排序之前,请检查null值

java - Eclipse Maven 和 Java 8 问题

Java 8 Optional 不能应用于接口(interface)

java - 用不同的值替换长字符串的一部分

java - Eclipse IDE : The resource could not be loaded because the App Transport Security policy requires the use of a secure connection

java - 在不受 Spring 容器管理的对象中使用 Spring bean 的正确方法是什么?

java - JavaFX 空数组列表

Java 8 : unit-testing a method that returns a Function object