我想比较 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 字节数组。
但由于您使用的是 Path
和 Files
,您至少使用 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/