1. Traditional data transfer
Traditional data transfers from the Socket network require 4 data copies and 4 context switches:
1. Read the disk file into the kernel buffer of the operating system. 2. Copy the data in the kernel buffer to the user space buffer. 3. The data is copied from the user-space buffer to the socket network sending buffer of the kernel. 4. Data is copied from the socket network sending buffer of the kernel to the buffer of the nic interface (hardware) for network transmission.
In the traditional way, it is very tedious to read the disk file and send it over the network after 4 data copies and 4 context switches. The actual I/O reading and writing required I/O interrupts and CPU response interrupts (bringing context switches). Although DMA was later introduced to take over the INTERRUPT requests from the CPU, the quad copy still had unnecessary links.
2. Zero copy implementation principle
The purpose of zero copy is to reduce unnecessary copies in the IO process and reduce the overhead of context switching between the user process address space and the kernel address space. Since a VM cannot operate the kernel directly, its implementation requires the support of the operating system (OS), that is, the kernel disclosure API.
2.1 Zero copy in Netty
ByteBuffer uses the Direct Buffer to implement zero-copy, which directly allocates space in the memory area to avoid the secondary memory copy of read and write data. This implements zero-copy of read and write sockets.
- If you use a traditional Heap Buffer for Socket reads and writes, the JVM copies the Heap Buffer to direct memory before writing it to the Socket. The message is sent with an extra memory copy of the buffer compared to direct out-of-heap memory.
2.CompositeByteBuf: Encapsulates multiple ByteBuFs into ByteBuFs and provides a unified encapsulated ByteBuf interface. The CompositeByteBuf does not actually combine buffers, but instead keeps references to them, avoiding copying data and achieving zero copy.
- In traditional Bytebuffers, if we want to combine the data from two bytebuffers, we first create a new array of size=size1+size2, and then copy the data from the two arrays into the new array. However, using Netty’s ByteBuf combination can avoid such operations.
3.Net Ty’s file transfer class DefaultFileRegion implements zero copy by calling filechannel.transferto (). Data in the file buffer is sent directly to the target Channel. The underlying call to The Linux operating system sendFile () implementation, data from the file by DMA engine copy to the kernel read buffer; DMA copies data from the kernel read buffer to the buffer of the nic interface (hardware) for network transmission.
2.2 Zero copy in Java
Zero copy is realized by filechannel.transferto () in Java, and sendFile () in Linux is called at the bottom. Data is copied from file to kernel read buffer by DMA engine. DMA copies data from the kernel read buffer to the buffer of the nic interface (hardware) for network transmission.
The filechannel.map () method in Java is used to implement zero copy. The underlying method is called mmap() in Linux, which maps the memory of the kernel buffer to the memory of the user buffer. This method is suitable for reading large files while also making changes to the file contents. However, if the data is subsequently sent through SocketChannel, the CPU is still required to copy the data.