Netty 零拷贝

1
Zero-Copy describes computer operations in which the CPU does not perform the task of copying data from one memory area to another.

磁盘数据通过网络发送

步骤

  1. 当应用程序发起read系统调用时,通过DMA(Direct Memory Access)将数据copy到内核空间buffer
  2. 然后由CPU控制将内核空间数据copy到用户空间下的 buffer
  3. read调用完成后,write调用首先将用户空间下 buffer中的数据copy到内核模式下的socket buffer
  4. 最后通过DMA将内核模式下的socket buffer中的数据copy到网卡buffer

缺点

数据从内核模式到用户模式走了一圈,浪费了两次copy,而这两次copy都是CPU copy(占用CPU资源)

操作系统 零拷贝

1
OS-level zero copy involves avoiding copying memory blocks from one location to another (typically from user space to kernel space) before sending data to the hardware driver (network card or disk drive) or vice versa.

典型场景:内核空间和用户空间的数据拷贝

Linux sendfile

os >= Linux 2.4内核

步骤
  1. DMA copy将磁盘数据copykernel buffer
  2. socket buffer中追加当前要发送的数据在kernel buffer中的位置和偏移量
  3. DMA gather copy(需要网卡支持数据收集模式)根据socket buffer中的位置和偏移量直接将kernel buffer中的数据copy到网卡上
优点

程序只需发出一次系统调用sendfile(),数据只经过了2次copy就从磁盘传送出去了,没有CPU copy

nginxjava FileChannel.transferTo()等在Linux系统中都引用了sendfile机制

FileChannel.transferTo(Java中的零拷贝)

Java NIOFileChannel.transferTo(long position, long count, WriteableByteChannel target)方法将当前通道中的数据传送到目标通道中,在支持Zero-Copylinux系统中,transferTo()的实现依赖于sendfile()调用

Netty零拷贝

  1. Netty的接收和发送ByteBuffer采用DIRECT BUFFERS,使用堆外内存进行Socket读写,不需要进行字节缓冲区的二次拷贝。如果使用传统的堆内存(HEAP BUFFERS)进行Socket读写,JVM会将堆内存Buffer拷贝一份到直接内存中,然后才写入Socket中。相比于堆外直接内存,消息在发送过程中多了一次缓冲区的内存拷贝。
  2. Netty提供了CompositeByteBuf对象,可以聚合多个ByteBuffer对象,用户可以像操作一个Buffer那样方便的对组合Buffer进行操作,避免了传统通过内存拷贝的方式将几个小Buffer合并成一个大的Buffer

  3. Netty的文件传输采用了java nio transferTo方法,它可以直接将文件缓冲区的数据发送到目标Channel(传统的做法: 拷贝文件内容到临时 buffer, 然后再将 buffer 写入Channel),使用操作系统级别的零拷贝,避免了传统通过循环write方式导致的内存拷贝问题

CompositeByteBuf

注意: CompositeByteBuf 是由多个 ByteBuf 组合而成的, 不过在 CompositeByteBuf 内部, 这些 ByteBuf 都是单独存在的, CompositeByteBuf 保存了它们的引用,只是在逻辑上是一个整体

java ByteBuffer vs netty ByteBuf

java 本身就有 ByteBuffer,为什么要额外设计一个 ByteBuf?

  • ByteBuffer 只用一个 position 变量表示当前位置,所以在进行读写切换的时候都需要调用flip()clear()等方法,否则功能将出错
  • ByteBuf 使用 readerIndexwriterIndex 分别表示读写位置,不需要调用函数切换,体验更好。

参考

磁盘及网络IO工作方式解析

Is Netty’s Zero Copy different from OS level Zero Copy?

深入浅出Netty - ByteBuf 和 ByteBufPool

热评文章