Serenely Fast I/O Buffer - C++ 高性能消息缓冲实现
概述
SereneDB 团队开发了一个高性能的并发 I/O 消息缓冲区 sdb::message::Buffer,在基准测试中比 Facebook 的 Folly IOBuf 最高快 45%。
背景
高负载服务需要优化网络数据传输并转向异步模型来发送和接收。这引入了另一个瓶颈:在发送之前将数据存储在缓冲区中。
需求
- FIFO:保持消息顺序
- 无限大小:缓冲区需要可扩展
现有方案的问题
虽然有很多消息缓冲区实现(Folly IOBuf、Abseil Cord、Seastar I/O Buffer 等),但团队找不到完美的方案,因为:
- 有些不支持并发读写
- 有些不够快
实现细节
SPSC 设计
sdb::message::Buffer 是 SPSC(单生产者单消费者)设计。这种弱约束实现了最有效的无锁解决方案,具有最少的原子操作。
缓冲区只有一个原子变量 _send_end,定义可读数据的结尾。
消息类型
- Flushed data(刷新数据):紧急的,必须立即发送
- Committed data(提交数据):不紧急,可以等待
- Uncommitted data(未提交数据):不能被读取,必须先提交
Flush 机制
写入消息时,可以设置 need_flush:
true- 立即刷新(发送所有数据)false- 仅在缓冲区超过阈值时刷新
基准测试结果
测试环境
AMD Ryzen 9 9950X 16-Core Processor,使用 jemalloc
100,000,000 个数据包(中位数 14 字节)
| 实现 | 时间 | sdb 更快 |
|---|---|---|
| folly_appender | 886,926,752 ns | - |
| sdb_buffer | 884,418,159 ns | -0.28% |
1,000,000 个数据包(中位数 0.3 KB)
| 实现 | 时间 | sdb 更快 |
|---|---|---|
| folly_appender | 28,003,500 ns | - |
| sdb_buffer | 26,055,791 ns | -6.96% |
1,000,000 个数据包(中位数 2.6 KB)
| 实现 | 时间 | sdb 更快 |
|---|---|---|
| folly_appender | 365,769,290 ns | - |
| sdb_buffer | 233,751,244 ns | -36.09% |
10,000 个数据包(中位数 82 KB)
| 实现 | 时间 | sdb 更快 |
|---|---|---|
| folly_appender | 90,551,226 ns | - |
| sdb_buffer | 49,762,329 ns | -45.06% |
结论
sdb::message::Buffer 在所有测试用例中都比 Folly appender 更快。虽然没有多显著,但这是诚实的工作。
WOW! 在大数据包(82 KB)中,sdb::message::Buffer 比 Folly appender 快 45%!
链接
- GitHub: https://github.com/serenedb/serenedb
- 基准测试代码: io_buffers.cpp