How Zero‑Copy Boosts Data Transfer: IO Mechanisms, mmap, sendfile & splice Explained
This article explains the concept of zero‑copy, compares traditional I/O copying with mmap, sendfile, DMA scatter/gather and splice techniques, and shows how Java NIO leverages mmap and sendfile to achieve high‑performance data transfer while minimizing CPU involvement.
01. Background Introduction
Many readers have encountered the term "zero‑copy" and wonder what it actually means. Literally, "zero" means zero copy operations and "copy" means moving data between storage areas, so zero‑copy means data does not need to be copied from one storage region to another.
In Linux 2.4 kernel, the sendfile system call can move disk data to a kernel buffer via DMA and then directly to a NIC buffer without CPU copying; this process is called zero‑copy.
From an OS perspective, zero‑copy does not eliminate data movement; it removes the CPU copy step, reducing unnecessary copies and improving efficiency.
02. IO Copy Mechanism Introduction
2.1 Traditional Data Copy Process
When a client downloads a file, the server performs two main steps: read the file from disk and transmit it over the network. The traditional flow involves:
Application calls
read, causing a CPU context switch from user to kernel mode.
OS uses DMA to move data from disk to a kernel buffer.
CPU copies data from the kernel buffer to a user buffer, causing a second context switch back to user mode.
This results in one DMA copy, one CPU copy, and two CPU context switches for each read or write operation.
2.2 mmap Memory‑Mapped Copy Process
mmap maps the user buffer directly to the kernel buffer, eliminating the CPU copy between them. The flow reduces the number of CPU copies while keeping the same DMA operations.
Data copies: 2 DMA copies, 1 CPU copy.
CPU switches: 4 (user↔kernel).
2.3 Linux sendfile Copy Process
In Linux 2.1,
sendfilemoves data from disk to a kernel buffer via DMA, then directly to a socket buffer, and finally to the network interface via DMA.
Data copies: 2 DMA copies, 1 CPU copy.
CPU switches: 2 (user↔kernel).
2.4 sendfile with DMA Scatter/Gather
Linux 2.4 introduced SG‑DMA support, allowing DMA to read directly from kernel space to the NIC, eliminating the CPU copy step.
Data copies: 2 DMA copies, 0 CPU copies.
CPU switches: 2 (user↔kernel).
2.5 Linux splice Zero‑Copy Process
Linux 2.6.17 added the
splicesystem call, which creates a pipe between the kernel buffer and the socket buffer, avoiding CPU copies without requiring special hardware.
Data copies: 2 DMA copies, 0 CPU copies.
CPU switches: 2 (user↔kernel).
03. IO Copy Mechanism Comparison
The table below summarizes the copy counts and context switches for each method. All zero‑copy techniques rely on OS support; the choice depends on the kernel implementation.
04. Related Concepts
4.1 DMA (Direct Memory Access)
DMA is a hardware feature that allows peripheral devices to transfer data directly to or from memory without CPU intervention, reducing CPU load.
4.2 Kernel Space and User Space
The operating system kernel runs in kernel space with full hardware access, while applications run in user space with restricted privileges. Data must be transferred between these spaces via system calls, which is where zero‑copy techniques operate.
05. Java Zero‑Copy Implementation
Java supports two zero‑copy mechanisms provided by the underlying Linux kernel: mmap and sendfile.
5.1 Java NIO support for mmap
Java NIO’s
MappedByteBufferclass maps a file directly into memory, invoking the Linux
mmapAPI.
<code>public static void main(String[] args) {
try {
FileChannel readChannel = FileChannel.open(Paths.get("a.txt"), StandardOpenOption.READ);
// Create memory‑mapped file
MappedByteBuffer data = readChannel.map(FileChannel.MapMode.READ_ONLY, 0, 1024 * 1024 * 40);
FileChannel writeChannel = FileChannel.open(Paths.get("b.txt"), StandardOpenOption.WRITE, StandardOpenOption.CREATE);
// Copy data
writeChannel.write(data);
// Close channels
readChannel.close();
writeChannel.close();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
</code>5.2 Java NIO support for sendfile
Java NIO’s
FileChannel.transferTomethod ultimately calls the Linux
sendfilesystem call when the OS provides it.
<code>public static void main(String[] args) {
try {
// Source file
FileChannel srcChannel = FileChannel.open(Paths.get("a.txt"), StandardOpenOption.READ);
// Destination file
FileChannel destChannel = FileChannel.open(Paths.get("b.txt"), StandardOpenOption.WRITE, StandardOpenOption.CREATE);
// Transfer data
srcChannel.transferTo(0, srcChannel.size(), destChannel);
// Close channels
srcChannel.close();
destChannel.close();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
</code>06. Summary
Zero‑copy does not mean data is never copied; it means the CPU copy step is omitted, reducing unnecessary copies and improving throughput. In Linux, the widely recognized zero‑copy methods are
sendfileand
splice, which rely entirely on DMA without CPU involvement.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.