跳到主要内容
英文版本为准

本页译自英文,由模型翻译。若与英文原文存在差异,以英文原文为准。

基准测试

ruststream-fred 在每条消息上的开销:与裸 fred 客户端对照的吞吐量,以及它自身代码的指令数和内存分配次数。

与裸客户端对照​

第一张图在真实的 Redis 服务器上把每个场景用三种方式运行。裸客户端 是在 fred 上手写的循环。Broker crate 是在本 crate 上写的同一个循环:Broker、订阅、投递流和 ack,上面没有运行时。RustStream 是用户写的服务:应用里的一个 #[subscriber] 处理器。第一项差值是本 crate 比它所封装的客户端多付出的开销,第二项是运行时在其上增加的开销。

每个循环画成一条横条,从最佳一轮延伸到最慢的一轮,圆点标出最佳一轮,缺口标出中位一轮。坐标轴的零点是裸客户端的最佳一轮,圆点在零点右侧表示更慢。空心圆点表示该循环与裸客户端的差异小于各轮的波动范围。图表下方的表格列出最佳一轮,括号里是中位一轮。

测量的形式有三种,每种传输方式一种:通过消费者组读取并确认每个条目的流、可靠列表,以及一个 Pub/Sub 频道。每种形式都分别在单机服务器、集群和 Sentinel 之后的主节点上运行。在集群上,Pub/Sub 一行使用分片形式,即 SSUBSCRIBE 和 SPUBLISH,集群上用的正是这种形式。

代码的开销​

第二张图统计一条消息在服务线程上的开销:稳态下 callgrind 测得的指令数和 DHAT 测得的内存分配次数。每个场景都是一个基于 RedisBroker 的服务,连接测试环境的单机服务器。服务运行在单线程运行时上,fred 也在同一线程上驱动它的连接,因此计数包括运行时、本 crate,以及 fred 编写命令和解析应答的工作。服务器是另一个进程,不计入。冷启动 是连接连接池、创建组、打开订阅并取得第一次投递一次性付出的开销。

流场景用 XREADGROUP 读取消费者组,用 XACK 结算,用 XADD 应答。可靠列表用 BLMOVE 认领每个条目,用 LREM 结算它。Pub/Sub 场景读取一个频道或一个模式,不结算任何东西。.pipeline() 场景把一次读取的结算一起发送,它的处理器每次投递排入一条 INCR;.pipeline().atomic() 把每次投递的段包进 MULTI 和 EXEC,窗口一页用图说明了这一点。

结果​

与裸客户端对照各循环比裸客户端最佳一轮低多少
  • 裸客户端
  • Broker crate
  • RustStream
  • 各轮,从最佳到最慢
  • 最佳一轮
  • 中位一轮
  • 轮次的波动范围
  • 无法区分

ruststream-fred 0.7.0 on ruststream 0.7.0-rc.11, AMD Ryzen 9 7900X 12-Core Processor, Linux 7.2.7-x64v3-xanmod1-1, redis:7-alpine in Docker on the host network, persistence off: a standalone server, a six-node cluster and a master behind Sentinel, 测量于 2026-09-27. 这些数字是怎样测得的

Redis Streams consumer group, standalone, 512 B JSON, ack each
  • 无法区分
  • 无法区分 (受 Broker 限制)
Redis Streams consumer group, cluster, 512 B JSON, ack each
  • 无法区分
  • 无法区分 (受 Broker 限制)
Redis Streams consumer group, sentinel, 512 B JSON, ack each
  • 无法区分
  • 无法区分 (受 Broker 限制)
Redis list work queue (reliable), standalone, 512 B JSON, ack each
  • +2%
  • +3.3% (受 Broker 限制)
Redis list work queue (reliable), cluster, 512 B JSON, ack each
  • 无法区分
  • 无法区分 (受 Broker 限制)
Redis list work queue (reliable), sentinel, 512 B JSON, ack each
  • 无法区分
  • 无法区分 (受 Broker 限制)
Redis Pub/Sub, standalone, 512 B JSON, no acknowledgement
  • 无法区分
  • 无法区分
Redis Pub/Sub (sharded), cluster, 512 B JSON, no acknowledgement
  • 无法区分
  • 无法区分
Redis Pub/Sub, sentinel, 512 B JSON, no acknowledgement
  • 无法区分
  • 无法区分
以表格显示数字
场景裸客户端Broker crateRustStream额外开销
Redis Streams consumer group, standalone, 512 B JSON, ack each51,326 msg/s (51,293)51,036 msg/s (50,247) (比客户端 无法区分)50,739 msg/s (49,943)无法区分 (受 Broker 限制)
Redis Streams consumer group, cluster, 512 B JSON, ack each39,596 msg/s (34,982)38,674 msg/s (34,977) (比客户端 无法区分)38,363 msg/s (34,554)无法区分 (受 Broker 限制)
Redis Streams consumer group, sentinel, 512 B JSON, ack each40,743 msg/s (40,444)40,202 msg/s (40,034) (比客户端 无法区分)40,213 msg/s (38,946)无法区分 (受 Broker 限制)
Redis list work queue (reliable), standalone, 512 B JSON, ack each29,548 msg/s (29,342)28,970 msg/s (28,639) (比客户端 +2%)28,575 msg/s (28,514)+3.3% (受 Broker 限制)
Redis list work queue (reliable), cluster, 512 B JSON, ack each22,656 msg/s (22,216)22,449 msg/s (22,290) (比客户端 无法区分)22,128 msg/s (22,002)无法区分 (受 Broker 限制)
Redis list work queue (reliable), sentinel, 512 B JSON, ack each23,372 msg/s (21,630)22,720 msg/s (22,374) (比客户端 无法区分)22,562 msg/s (21,649)无法区分 (受 Broker 限制)
Redis Pub/Sub, standalone, 512 B JSON, no acknowledgement402,530 msg/s (397,136)400,183 msg/s (400,038) (比客户端 无法区分)397,976 msg/s (394,780)无法区分
Redis Pub/Sub (sharded), cluster, 512 B JSON, no acknowledgement297,850 msg/s (295,380)295,819 msg/s (292,015) (比客户端 无法区分)290,276 msg/s (289,083)无法区分
Redis Pub/Sub, sentinel, 512 B JSON, no acknowledgement358,378 msg/s (353,940)355,630 msg/s (352,911) (比客户端 无法区分)395,136 msg/s (351,006)无法区分
代码的开销

AMD Ryzen 9 7900X 12-Core Processor, x86_64, 427-5912 MHz, 12 physical, 24 logical, 62.4 GiB, unknown, Linux 7.2.7-x64v3-xanmod1-1, 1.98.1, 3.25.1, bench, inheriting release (opt-level = 3, lto = false, codegen-units = 16), ruststream-fred default (none), ruststream macros,json (the service loop only). ruststream-fred 0.7.0, ruststream 0.7.0-rc.11, 测量于 2026-09-27.

指令数
内存分配
stream consumer group, JSON decode into a small struct, XACK each
32,860.7
29.7
stream reply, appended with XADD through RedisPublish
53,459.4
44.7
stream consumer group in batches of 64, XACK each
33,166.8
29.8
reliable list, JSON decode into a small struct, LREM each
39,668
26
Pub/Sub channel, JSON decode into a small struct
8,768.7
6
Pub/Sub pattern, JSON decode into a small struct
9,135.9
6
stream with .pipeline(), one INCR queued per delivery
38,225.6
39.2
stream with .pipeline().atomic(), one INCR queued per delivery
78,086.7
71.8
reliable list with .pipeline(), one INCR queued per delivery
57,556.1
48.9
reliable list with .pipeline().atomic(), one INCR queued per delivery
82,776.9
68.6
Pub/Sub channel with .pipeline(), one INCR queued per delivery
31,151.8
27.1
Pub/Sub channel with .pipeline().atomic(), one INCR queued per delivery
56,240.5
47.3
Pub/Sub pattern with .pipeline(), one INCR queued per delivery
31,525.9
27.1
Pub/Sub pattern with .pipeline().atomic(), one INCR queued per delivery
56,420.4
47.3
以表格显示数字
场景指令数内存分配冷启动
stream consumer group, JSON decode into a small struct, XACK each32,860.729.7777,211 / 467
stream reply, appended with XADD through RedisPublish53,459.444.7814,951 / 483
stream consumer group in batches of 64, XACK each33,166.829.8798,525 / 470
reliable list, JSON decode into a small struct, LREM each39,66826727,658 / 415
Pub/Sub channel, JSON decode into a small struct8,768.76916,144 / 402
Pub/Sub pattern, JSON decode into a small struct9,135.96915,955 / 397
stream with .pipeline(), one INCR queued per delivery38,225.639.2820,308 / 515
stream with .pipeline().atomic(), one INCR queued per delivery78,086.771.8839,410 / 523
reliable list with .pipeline(), one INCR queued per delivery57,556.148.92,630,559 / 1,941
reliable list with .pipeline().atomic(), one INCR queued per delivery82,776.968.62,648,107 / 1,949
Pub/Sub channel with .pipeline(), one INCR queued per delivery31,151.827.1946,874 / 433
Pub/Sub channel with .pipeline().atomic(), one INCR queued per delivery56,240.547.3963,733 / 447
Pub/Sub pattern with .pipeline(), one INCR queued per delivery31,525.927.1945,783 / 428
Pub/Sub pattern with .pipeline().atomic(), one INCR queued per delivery56,420.447.3962,695 / 442

机器​

处理器AMD Ryzen 9 7900X 12-Core Processor
架构x86_64
频率427-5912 MHz
核心数12 physical, 24 logical
内存62.4 GiB
内存速度unknown
操作系统Linux 7.2.7-x64v3-xanmod1-1
Brokerredis:7-alpine in Docker on the host network, persistence off: a standalone server, a six-node cluster and a master behind Sentinel
往返时间standalone 22 µs, cluster 25 µs, sentinel 24 µs (one EXISTS and its answer)
编译器1.98.1
构建配置bench, inheriting release (opt-level = 3, lto = false, codegen-units = 16)
特性ruststream-fred default (none), ruststream macros,json (the service loop only)
RUSTFLAGSnone (the recipe clears RUSTFLAGS, so the numbers are not tied to this CPU)
Valgrind3.25.1

数字来自本版本的 docs/benchmarks/results.json,由基准测试命令写入,测量时使用的构建配置就是上面记录的那一个。方法论说明它们是怎样测得的,数字说明可以从中得出什么结论。