抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

什么是零拷贝

零拷贝(Zero-copy):指计算机执行操作时,cpu不需要先将数据从某处内存复制到另一个特定区域。这种技术通常用于通过网络传输文件时节省CPU周期和内存带宽。

好处:

  1. 可以减少数据拷贝和共享总线操作的次数,消除传输数据在存储器之间不必要的中间拷贝次数,从而有效地提高数据传输效率。
  2. 零拷贝技术减少了用户进程地址空间和内核空间之间因为上下文切换带来的开销

Linux IO流程

  1. DMA拷贝:通过DMA方式将文件从硬盘拷贝到内核缓冲区域
  2. CPU拷贝:从内核缓冲区拷贝到用户用户空间缓冲区

读取一个文件然后通过Socket发送的流程

  1. File.read(fileDesc,buf,len);
  2. Socket.send(socket,buf,len);

在上述过程中经历了四次拷贝:2次cpucopy,2次dma copy,4次上下文切换

怎么实现零拷贝

零拷贝实际上就是减少IO流程中不必要的拷贝,需要操作系统的支持。通过直接将ReadBUfferkao拷贝到内核的SocketBuffer这样减少了一次cpu拷贝和两次上下文切换。

Java零拷贝的使用

1 内存映射(mmap)

将内核缓冲区映射到用户缓冲区,通过虚拟内存器实现,(存在时空开销所以不适合小文件)。Java通过MappedByteBUffer实现。cpu拷贝次数一次,dma拷贝次数不变。上下文切换四次

1
2
3
4
5
File file = new File("data.zip");
RandomAccessFile rad = new RandomAccessFile(file,"rw");
FileChannel filechannel = raf.getChannel();
MappedByteBuffer buffer = filechannel.map(FileChannel.MapMode.READ_ONLY,0,filechannel.size());

3 JavaNIO FileChannel.transferTo

Linux2.1 提供了sendfile系统调用。可以实现内核读缓冲到socket缓冲的拷贝。一次cpu拷贝和两次DMA拷贝。两次上下文切换。

1
2
3
4
5
6
File file = new File("test.zip");         
RandomAccessFile raf = new RandomAccessFile(file, "rw");
FileChannel fileChannel = raf.getChannel();
SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("", 1234));
// 直接使用了transferTo()进行通道间的数据传输
fileChannel.transferTo(0, fileChannel.size(), socketChannel);

Netty中的零拷贝

哪里用到了零拷贝

  1. kafka
  2. Netty
  3. RocketMQ
  4. Nginx
  5. Apache

评论