为什么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();
}
}