How Zero‑Copy and Async I/O Supercharge Large File Transfers
The article explains why the naïve approach of reading a file into a small user‑space buffer and sending it piece‑by‑piece is inefficient, and how zero‑copy, PageCache, asynchronous I/O and direct I/O can dramatically reduce context switches, memory copies, and CPU usage for high‑throughput file transfers.
Naïve file‑transfer implementation
Typical server‑side file transfer reads a file from disk into a 32 KB user‑space buffer, then loops 10 000 times to send each chunk via read and write system calls. For a 320 MB file this incurs about 40 000 context switches and four times the original data volume due to repeated memory copies.
Why the naïve method is slow
Context switches : each 32 KB chunk requires a read and a write system call, causing two switches (user→kernel and kernel→user) per call. Over 10 000 chunks this totals roughly 40 000 switches, which adds noticeable latency under high concurrency.
Memory copies : the data is copied from disk to the kernel page cache, then to the user buffer, and finally to the socket buffer, resulting in four copies for the whole file (≈1.28 GB for a 320 MB file).
Zero‑copy technique
Zero‑copy eliminates the user‑space buffer. The kernel moves data directly from the page cache to the socket buffer, reducing system calls to a single sendfile -like operation. This cuts context switches to two and memory copies to three, or even two when the NIC supports scatter‑gather DMA.
PageCache basics
When a file is read, the kernel first copies the data into PageCache (a memory‑resident cache of recent disk blocks) and then copies it to the requesting process. PageCache speeds up repeated reads by exploiting temporal locality and pre‑reading, but it also introduces an extra memory copy.
For large files that rarely get re‑accessed, PageCache can become a liability: it occupies valuable cache space, evicts hot small files, and adds unnecessary copies, especially when combined with zero‑copy.
When to avoid zero‑copy
In high‑concurrency scenarios with many gigabyte‑scale files, PageCache may be saturated, causing small files to suffer and overall performance to drop. In such cases, bypassing PageCache (and thus zero‑copy) is preferable.
Asynchronous I/O + Direct I/O
Asynchronous I/O (AIO) eliminates the blocking read call by issuing a read request to the kernel and returning immediately. The kernel notifies the process when data is ready, allowing other work to proceed.
However, AIO traditionally does not use PageCache, which means it cannot benefit from cache‑based optimizations. Direct I/O explicitly tells the kernel to bypass PageCache and transfer data straight between disk and user buffers.
Direct I/O is useful when the application already implements its own caching (e.g., databases like MySQL) or when transferring very large files where PageCache would be counter‑productive.
Combining AIO with Direct I/O lets large files be read without blocking and without extra copies, while small files can still be served efficiently with zero‑copy.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
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.
