目录
之前学习的一些文档:
零拷贝技术 文件传输(读取与发送)中的拷贝与上下文切换 https://www.wolai.com/9ya76io6rbUXFki99avf2L
之前都是纸上谈兵,这次让我们利用这原理来实现queue
零拷贝队列实现文档
本文档详细说明了三种零拷贝队列的实现方式:SendfileQueue、MmapQueue和SpliceQueue。
classDiagram
QueueBase <|-- SendfileQueue
QueueBase <|-- MmapQueue
QueueBase <|-- SpliceQueue
class QueueBase {
<<abstract>>
+~QueueBase()
+enqueue(data: char, size: size_t) bool
+dequeue(buffer: char, size: size_t) ssize_t
}
class SendfileQueue {
-data_fd_: int
-write_pos_: size_t
-read_pos_: size_t
-max_size_: size_t
+SendfileQueue(data_file: string, max_size: size_t)
+~SendfileQueue()
+enqueue(data: char, size: size_t) bool
+dequeue(buffer: char, size: size_t) ssize_t
}
class MmapQueue {
-data_fd_: int
-buffer_: char
-write_pos_: size_t
-read_pos_: size_t
-max_size_: size_t
+MmapQueue(data_file: string, max_size: size_t)
+~MmapQueue()
+enqueue(data: char, size: size_t) bool
+dequeue(buffer: char, size: size_t) ssize_t
}
class SpliceQueue {
-data_fd_: int
-pipe_fds_: int[2]
-write_pos_: size_t
-read_pos_: size_t
-max_size_: size_t
+SpliceQueue(data_file: string, max_size: size_t)
+~SpliceQueue()
+enqueue(data: char, size: size_t) bool
+dequeue(buffer: char, size: size_t) ssize_t
}实现流程图
SendfileQueue实现流程
MmapQueue实现流程
flowchart TD
subgraph Enqueue
E1[开始] --> E2{检查空间}
E2 -->|足够| E3[memcpy到映射内存]
E2 -->|不足| E4[返回失败]
E3 --> E5[更新write_pos]
E5 --> E6[返回成功]
end
subgraph Dequeue
D1[开始] --> D2{检查数据}
D2 -->|有数据| D3[计算可读取量]
D2 -->|无数据| D4[返回0]
D3 --> D5[memcpy到buffer]
D5 --> D6[更新read_pos]
D6 --> D7[返回读取字节数]
endflowchart TD
subgraph Enqueue
E1[开始] --> E2{检查空间}
E2 -->|足够| E3[分批处理]
E2 -->|不足| E4[返回失败]
E3 --> E5[write写入管道]
E5 --> E6[splice到文件]
E6 --> E7[更新write_pos]
E7 --> E8[返回成功]
end
subgraph Dequeue
D1[开始] --> D2{检查数据}
D2 -->|有数据| D3[分批处理]
D2 -->|无数据| D4[返回0]
D3 --> D5[splice到管道]
D5 --> D6[read读取到buffer]
D6 --> D7[更新read_pos]
D7 --> D8[返回读取字节数]
end时序图
SendfileQueue操作时序
MmapQueue操作时序
sequenceDiagram
participant C as Client
participant Q as MmapQueue
participant M as MappedMemory
participant F as DataFile
%% 初始化
C->>+Q: 构造函数
Q->>+F: open文件
Q->>F: ftruncate设置大小
Q->>+M: mmap映射文件
M-->>-Q: 返回映射内存
F-->>-Q: 返回文件描述符
Q-->>-C: 返回实例
%% Enqueue操作
C->>+Q: enqueue(data, size)
Q->>+M: memcpy数据
M-->>-Q: 复制完成
Q-->>-C: success/failure
%% Dequeue操作
C->>+Q: dequeue(buffer, size)
Q->>+M: memcpy到buffer
M-->>-Q: 复制完成
Q-->>-C: 返回数据/错误sequenceDiagram
participant C as Client
participant Q as SpliceQueue
participant P as Pipe
participant F as DataFile
%% Enqueue操作
C->>+Q: enqueue(data, size)
loop 每个64KB批次
Q->>+P: write写入批次
P-->>-Q: 写入完成
Q->>+F: splice从管道到文件
F-->>-Q: splice完成
end
Q-->>-C: success/failure
%% Dequeue操作
C->>+Q: dequeue(buffer, size)
loop 每个64KB批次
Q->>+F: splice到管道
F-->>-Q: splice完成
Q->>+P: read到buffer
P-->>-Q: 读取完成
end
Q-->>-C: 返回数据/错误性能特点分析
SendfileQueue
- 优点
- 实现简单直观
- 使用sendfile系统调用避免用户空间拷贝
- 适合整块数据传输
- 缺点
- 需要创建临时文件
- dequeue操作有额外的文件I/O开销
- 不适合高频小数据操作
MmapQueue
- 优点
- 直接内存操作,速度最快
- 读写操作都是简单的内存拷贝
- 适合频繁的读写操作
- 缺点
- 占用虚拟内存空间
- 大文件映射需要注意内存管理
- 需要处理内存映射失败的情况
SpliceQueue
- 优点
- 完全零拷贝,不涉及用户空间
- 内存占用小
- 适合大数据流传输
- 缺点
- 实现较复杂
- 需要管理管道缓冲区
- 分批处理增加了代码复杂度
使用建议
- 小数据量、高频访问场景
- 推荐使用MmapQueue
- 直接内存操作性能最好
- 避免系统调用开销
- 大数据量、内存受限场景
- 推荐使用SpliceQueue
- 避免内存映射的开销
- 完全零拷贝传输
- 简单实现、临时文件可接受场景
- 推荐使用SendfileQueue
- 实现简单,易于维护
- 适合不频繁的大块数据传输
性能测试结果
基于1GB数据量、1MB消息大小的测试结果:
队列类型
入队时间(ms)
出队时间(ms)
总吞吐量(GB/s)
SendfileQueue
~500
~700
~1.6
MmapQueue
~500
~200
~2.6
SpliceQueue
~600
~400
~2.0
注:实际性能可能因硬件配置和系统负载而异。
Starting Zero-Copy Queue Performance Tests
=========================================
Testing Sendfile Queue...
Configuration:
- Queue size: 1024 MB
- Message size: 1024 KB
- Number of messages: 1000
- Total data: 1000 MB
Generating test data...
Starting enqueue test...
Progress: 100%%
Starting dequeue test...
Progress: 100%%
Performance Results:
- Enqueue time: 358ms
- Dequeue time: 777ms
- Total time: 1135ms
- Throughput: 1.72 GB/s
- Messages/sec: 1762
Testing Mmap Queue...
Configuration:
- Queue size: 1024 MB
- Message size: 1024 KB
- Number of messages: 1000
- Total data: 1000 MB
Generating test data...
Starting enqueue test...
Progress: 100%%
Starting dequeue test...
Progress: 100%%
Performance Results:
- Enqueue time: 450ms
- Dequeue time: 271ms
- Total time: 721ms
- Throughput: 2.71 GB/s
- Messages/sec: 2774
Testing Splice Queue...
Configuration:
- Queue size: 1024 MB
- Message size: 1024 KB
- Number of messages: 1000
- Total data: 1000 MB
Generating test data...
Starting enqueue test...
Progress: 100%%
Starting dequeue test...
Progress: 100%%
Performance Results:
- Enqueue time: 398ms
- Dequeue time: 229ms
- Total time: 627ms
- Throughput: 3.12 GB/s
- Messages/sec: 3190
Comments 0
Sign in to comment and like
← More postsThat’s all for now. Thanks for reading.
MmapQueue实现流程
flowchart TD
subgraph Enqueue
E1[开始] --> E2{检查空间}
E2 -->|足够| E3[memcpy到映射内存]
E2 -->|不足| E4[返回失败]
E3 --> E5[更新write_pos]
E5 --> E6[返回成功]
end
subgraph Dequeue
D1[开始] --> D2{检查数据}
D2 -->|有数据| D3[计算可读取量]
D2 -->|无数据| D4[返回0]
D3 --> D5[memcpy到buffer]
D5 --> D6[更新read_pos]
D6 --> D7[返回读取字节数]
end
flowchart TD
subgraph Enqueue
E1[开始] --> E2{检查空间}
E2 -->|足够| E3[分批处理]
E2 -->|不足| E4[返回失败]
E3 --> E5[write写入管道]
E5 --> E6[splice到文件]
E6 --> E7[更新write_pos]
E7 --> E8[返回成功]
end
subgraph Dequeue
D1[开始] --> D2{检查数据}
D2 -->|有数据| D3[分批处理]
D2 -->|无数据| D4[返回0]
D3 --> D5[splice到管道]
D5 --> D6[read读取到buffer]
D6 --> D7[更新read_pos]
D7 --> D8[返回读取字节数]
end时序图
SendfileQueue操作时序
MmapQueue操作时序
sequenceDiagram
participant C as Client
participant Q as MmapQueue
participant M as MappedMemory
participant F as DataFile
%% 初始化
C->>+Q: 构造函数
Q->>+F: open文件
Q->>F: ftruncate设置大小
Q->>+M: mmap映射文件
M-->>-Q: 返回映射内存
F-->>-Q: 返回文件描述符
Q-->>-C: 返回实例
%% Enqueue操作
C->>+Q: enqueue(data, size)
Q->>+M: memcpy数据
M-->>-Q: 复制完成
Q-->>-C: success/failure
%% Dequeue操作
C->>+Q: dequeue(buffer, size)
Q->>+M: memcpy到buffer
M-->>-Q: 复制完成
Q-->>-C: 返回数据/错误sequenceDiagram
participant C as Client
participant Q as SpliceQueue
participant P as Pipe
participant F as DataFile
%% Enqueue操作
C->>+Q: enqueue(data, size)
loop 每个64KB批次
Q->>+P: write写入批次
P-->>-Q: 写入完成
Q->>+F: splice从管道到文件
F-->>-Q: splice完成
end
Q-->>-C: success/failure
%% Dequeue操作
C->>+Q: dequeue(buffer, size)
loop 每个64KB批次
Q->>+F: splice到管道
F-->>-Q: splice完成
Q->>+P: read到buffer
P-->>-Q: 读取完成
end
Q-->>-C: 返回数据/错误性能特点分析
SendfileQueue
- 优点
- 实现简单直观
- 使用sendfile系统调用避免用户空间拷贝
- 适合整块数据传输
- 缺点
- 需要创建临时文件
- dequeue操作有额外的文件I/O开销
- 不适合高频小数据操作
MmapQueue
- 优点
- 直接内存操作,速度最快
- 读写操作都是简单的内存拷贝
- 适合频繁的读写操作
- 缺点
- 占用虚拟内存空间
- 大文件映射需要注意内存管理
- 需要处理内存映射失败的情况
SpliceQueue
- 优点
- 完全零拷贝,不涉及用户空间
- 内存占用小
- 适合大数据流传输
- 缺点
- 实现较复杂
- 需要管理管道缓冲区
- 分批处理增加了代码复杂度
使用建议
- 小数据量、高频访问场景
- 推荐使用MmapQueue
- 直接内存操作性能最好
- 避免系统调用开销
- 大数据量、内存受限场景
- 推荐使用SpliceQueue
- 避免内存映射的开销
- 完全零拷贝传输
- 简单实现、临时文件可接受场景
- 推荐使用SendfileQueue
- 实现简单,易于维护
- 适合不频繁的大块数据传输
性能测试结果
基于1GB数据量、1MB消息大小的测试结果:
队列类型
入队时间(ms)
出队时间(ms)
总吞吐量(GB/s)
SendfileQueue
~500
~700
~1.6
MmapQueue
~500
~200
~2.6
SpliceQueue
~600
~400
~2.0
注:实际性能可能因硬件配置和系统负载而异。
Starting Zero-Copy Queue Performance Tests
=========================================
Testing Sendfile Queue...
Configuration:
- Queue size: 1024 MB
- Message size: 1024 KB
- Number of messages: 1000
- Total data: 1000 MB
Generating test data...
Starting enqueue test...
Progress: 100%%
Starting dequeue test...
Progress: 100%%
Performance Results:
- Enqueue time: 358ms
- Dequeue time: 777ms
- Total time: 1135ms
- Throughput: 1.72 GB/s
- Messages/sec: 1762
Testing Mmap Queue...
Configuration:
- Queue size: 1024 MB
- Message size: 1024 KB
- Number of messages: 1000
- Total data: 1000 MB
Generating test data...
Starting enqueue test...
Progress: 100%%
Starting dequeue test...
Progress: 100%%
Performance Results:
- Enqueue time: 450ms
- Dequeue time: 271ms
- Total time: 721ms
- Throughput: 2.71 GB/s
- Messages/sec: 2774
Testing Splice Queue...
Configuration:
- Queue size: 1024 MB
- Message size: 1024 KB
- Number of messages: 1000
- Total data: 1000 MB
Generating test data...
Starting enqueue test...
Progress: 100%%
Starting dequeue test...
Progress: 100%%
Performance Results:
- Enqueue time: 398ms
- Dequeue time: 229ms
- Total time: 627ms
- Throughput: 3.12 GB/s
- Messages/sec: 3190
MmapQueue操作时序
sequenceDiagram
participant C as Client
participant Q as MmapQueue
participant M as MappedMemory
participant F as DataFile
%% 初始化
C->>+Q: 构造函数
Q->>+F: open文件
Q->>F: ftruncate设置大小
Q->>+M: mmap映射文件
M-->>-Q: 返回映射内存
F-->>-Q: 返回文件描述符
Q-->>-C: 返回实例
%% Enqueue操作
C->>+Q: enqueue(data, size)
Q->>+M: memcpy数据
M-->>-Q: 复制完成
Q-->>-C: success/failure
%% Dequeue操作
C->>+Q: dequeue(buffer, size)
Q->>+M: memcpy到buffer
M-->>-Q: 复制完成
Q-->>-C: 返回数据/错误
sequenceDiagram
participant C as Client
participant Q as SpliceQueue
participant P as Pipe
participant F as DataFile
%% Enqueue操作
C->>+Q: enqueue(data, size)
loop 每个64KB批次
Q->>+P: write写入批次
P-->>-Q: 写入完成
Q->>+F: splice从管道到文件
F-->>-Q: splice完成
end
Q-->>-C: success/failure
%% Dequeue操作
C->>+Q: dequeue(buffer, size)
loop 每个64KB批次
Q->>+F: splice到管道
F-->>-Q: splice完成
Q->>+P: read到buffer
P-->>-Q: 读取完成
end
Q-->>-C: 返回数据/错误性能特点分析
SendfileQueue
- 优点
- 实现简单直观
- 使用sendfile系统调用避免用户空间拷贝
- 适合整块数据传输
- 缺点
- 需要创建临时文件
- dequeue操作有额外的文件I/O开销
- 不适合高频小数据操作
MmapQueue
- 优点
- 直接内存操作,速度最快
- 读写操作都是简单的内存拷贝
- 适合频繁的读写操作
- 缺点
- 占用虚拟内存空间
- 大文件映射需要注意内存管理
- 需要处理内存映射失败的情况
SpliceQueue
- 优点
- 完全零拷贝,不涉及用户空间
- 内存占用小
- 适合大数据流传输
- 缺点
- 实现较复杂
- 需要管理管道缓冲区
- 分批处理增加了代码复杂度
使用建议
- 小数据量、高频访问场景
- 推荐使用MmapQueue
- 直接内存操作性能最好
- 避免系统调用开销
- 大数据量、内存受限场景
- 推荐使用SpliceQueue
- 避免内存映射的开销
- 完全零拷贝传输
- 简单实现、临时文件可接受场景
- 推荐使用SendfileQueue
- 实现简单,易于维护
- 适合不频繁的大块数据传输
性能测试结果
- 实现简单直观
- 使用sendfile系统调用避免用户空间拷贝
- 适合整块数据传输
- 需要创建临时文件
- dequeue操作有额外的文件I/O开销
- 不适合高频小数据操作
- 直接内存操作,速度最快
- 读写操作都是简单的内存拷贝
- 适合频繁的读写操作
- 占用虚拟内存空间
- 大文件映射需要注意内存管理
- 需要处理内存映射失败的情况
- 完全零拷贝,不涉及用户空间
- 内存占用小
- 适合大数据流传输
- 实现较复杂
- 需要管理管道缓冲区
- 分批处理增加了代码复杂度
- 推荐使用MmapQueue
- 直接内存操作性能最好
- 避免系统调用开销
- 推荐使用SpliceQueue
- 避免内存映射的开销
- 完全零拷贝传输
- 推荐使用SendfileQueue
- 实现简单,易于维护
- 适合不频繁的大块数据传输
基于1GB数据量、1MB消息大小的测试结果:
| 队列类型 | 入队时间(ms) | 出队时间(ms) | 总吞吐量(GB/s) |
|---|---|---|---|
| SendfileQueue | ~500 | ~700 | ~1.6 |
| MmapQueue | ~500 | ~200 | ~2.6 |
| SpliceQueue | ~600 | ~400 | ~2.0 |
注:实际性能可能因硬件配置和系统负载而异。
Starting Zero-Copy Queue Performance Tests
=========================================
Testing Sendfile Queue...
Configuration:
- Queue size: 1024 MB
- Message size: 1024 KB
- Number of messages: 1000
- Total data: 1000 MB
Generating test data...
Starting enqueue test...
Progress: 100%%
Starting dequeue test...
Progress: 100%%
Performance Results:
- Enqueue time: 358ms
- Dequeue time: 777ms
- Total time: 1135ms
- Throughput: 1.72 GB/s
- Messages/sec: 1762
Testing Mmap Queue...
Configuration:
- Queue size: 1024 MB
- Message size: 1024 KB
- Number of messages: 1000
- Total data: 1000 MB
Generating test data...
Starting enqueue test...
Progress: 100%%
Starting dequeue test...
Progress: 100%%
Performance Results:
- Enqueue time: 450ms
- Dequeue time: 271ms
- Total time: 721ms
- Throughput: 2.71 GB/s
- Messages/sec: 2774
Testing Splice Queue...
Configuration:
- Queue size: 1024 MB
- Message size: 1024 KB
- Number of messages: 1000
- Total data: 1000 MB
Generating test data...
Starting enqueue test...
Progress: 100%%
Starting dequeue test...
Progress: 100%%
Performance Results:
- Enqueue time: 398ms
- Dequeue time: 229ms
- Total time: 627ms
- Throughput: 3.12 GB/s
- Messages/sec: 3190
Comments 0
Sign in to comment and like
No comments yet.