零拷贝原理
本文介绍零拷贝(Zero-Copy)的原理和应用场景。
什么是零拷贝
零拷贝是一种 I/O 操作优化技术…
零拷贝(Zero-Copy)实现原理
传统方式 vs 零拷贝
1
2
3
4
5
6
7
8
9传统方式:read() + write()
应用程序需要:
1. read()读取数据到用户空间
2. write()写入数据到socket缓冲区
零拷贝:sendfile()
应用程序:
1. 直接调用sendfile()系统调用
2. 内核直接在内核空间完成传输sendfile()系统调用
1
2
3
4
5// Linux系统调用
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
// Java NIO中的使用
FileChannel.transferTo(position, count, socketChannel);实现机制
1
2
3
4
5
6
7
8
9
10
11
12
13
14两种实现方式:
1. 带DMA收集功能的网卡:
┌─────────┐ ┌──────────┐ ┌─────────┐
│ 磁盘 │ -> │ 内核缓冲区│ => │ 网卡 │
└─────────┘ └──────────┘ └─────────┘
DMA拷贝 只传递描述符 DMA拷贝
(不复制数据)
2. 普通网卡:
┌─────────┐ ┌──────────┐ ┌──────────┐ ┌─────────┐
│ 磁盘 │ -> │ 内核缓冲区│ -> │socket缓冲区│ -> │ 网卡 │
└─────────┘ └──────────┘ └──────────┘ └─────────┘
DMA拷贝 CPU拷贝 DMA拷贝DMA收集功能原理
1
2
3
4
5
6
7
8
9核心机制:
1. 内核缓冲区不复制数据
2. 只向网卡传递内存描述符(sg_list)
3. 网卡根据描述符直接从内核缓冲区读取数据
描述符内容:
- 内存地址
- 数据长度
- 偏移量性能对比
1
2
3
4
5
6
7
8
9
10
11
12
13发送1GB文件:
传统方式:
- CPU拷贝:2次
- DMA拷贝:2次
- 上下文切换:4次
- 总耗时:~10秒
零拷贝(带DMA收集):
- CPU拷贝:0次
- DMA拷贝:2次
- 上下文切换:2次
- 总耗时:~3秒Kafka中的应用
1
2
3
4
5
6
7
8
9
10
11
12
13// Kafka源码中的使用
public class FileChannel {
public long transferTo(long position, long count, WritableByteChannel target) {
// 底层调用sendfile()
return transferTo0(position, count, target);
}
}
优势:
1. 减少CPU使用
2. 提高吞吐量
3. 降低内存使用
4. 减少上下文切换