使用splice()操作匿名内存是否具备性能优势?
splice Offer Performance Benefits for Anonymous Memory (e.g., memfd_create File Descriptors)? Short answer: Yes, absolutely—when used in the right scenarios, splice can deliver significant performance gains with memfd_create-backed file descriptors, thanks to its zero-copy (or minimal-copy) kernel-side data transfer.
Let’s break down why and when this matters:
Core Advantage of splice for MemFDs
First, remember how splice works: it moves data directly between two file descriptors entirely within the kernel address space, eliminating the costly double-copy (kernel → user → kernel) that comes with traditional read()/write() workflows.
Since memfd_create creates an anonymous, memory-resident file descriptor (no backing disk, data lives in kernel memory pages), it’s a perfect fit for splice’s strengths. The data never needs to touch user-space buffers unless you explicitly require it.
Scenarios Where the Performance Win Is Clear
1. Transferring Data Between MemFDs and Other Kernel-First Destinations/Sources
If you need to move data from a memFD to a socket (e.g., sending over the network), a pipe, or another memFD, splice shines:
- Traditional
read()/write()would copy data from the memFD’s kernel pages to a user-space buffer, then copy that buffer again to the target’s kernel space (like a socket’s send queue). That’s two copies plus two system calls. - With
splice, the kernel either:- Reassigns page table entries (using
SPLICE_F_MOVEif the pages are unmmapped and private) for zero-overhead transfer, or - Performs a single copy within the kernel (if pages are shared or mapped), which is far faster than crossing the user-kernel boundary twice.
- Reassigns page table entries (using
For example, sending a large memFD buffer over a socket with splice looks like this:
loff_t in_off = 0, out_off = 0; splice(memfd, &in_off, sockfd, &out_off, BUFFER_SIZE, SPLICE_F_MOVE | SPLICE_F_NONBLOCK);
This one system call replaces two separate read/write calls and eliminates user-space copies.
2. Bulk Data Movement Without User-Space Processing
If you don’t need to modify the data in user-space—just shuffle it between kernel-managed file descriptors—splice is unbeatable. Even for smaller datasets, the reduction in system call overhead and copy operations adds up, especially in high-throughput applications.
Scenarios Where splice Isn’t the Best Choice
- When you need to manipulate data in user-space: If you have to edit, parse, or transform the data before transferring, you’ll need to bring it into user-space anyway (via
mmaporread). In this case,splicedoesn’t offer any benefit. - Small, frequent data transfers: The overhead of the
splicesystem call might not outweigh the gains for tiny chunks of data. Stick toread/writeormmaphere.
Key Caveats
- Kernel Version Support:
memfd_createwas added in Linux 3.17, and fullsplicecompatibility with memFDs requires a reasonably recent kernel (post-4.x is safest). Older kernels may have limited support or fallback to slower paths. SPLICE_F_MOVELimitations: The zero-copySPLICE_F_MOVEflag only works if the memFD’s pages aren’t mapped to user-space (viammap) and are private. If pages are shared or mapped, the kernel will fallback to a kernel-side copy—still better than user-space copies, but not true zero-copy.
Final Takeaway
Use splice with memfd_create when you’re moving data between kernel-managed file descriptors and don’t need to touch the data in user-space. For these use cases, you’ll see measurable improvements in throughput and reduced CPU usage compared to traditional read/write workflows.
内容的提问来源于stack exchange,提问作者salient

