这是一个用Rust编写的低延迟线程间通信库。
它深受出色的LMAX Disruptor库的启发。
在你的Cargo.toml文件中添加以下内容:
disruptor = "3.2.0"
要了解如何使用该库的详细信息,请查看docs.rs/disruptor上的文档。
以下是一个最小示例,演示了单个和批量发布。注意,为了获得最佳延迟和吞吐量,应尽可能使用批量发布(参见下面的基准测试)。
use disruptor::*; // 环形缓冲区中的事件。 struct Event { price: f64 } fn main() { // 用于初始化环形缓冲区中事件的工厂闭包。 let factory = || { Event { price: 0.0 }}; // 用于处理事件的闭包。 let processor = |e: &Event, sequence: Sequence, end_of_batch: bool| { // 在这里添加你的处理逻辑。 }; let size = 64; let mut producer = disruptor::build_single_producer(size, factory, BusySpin) .handle_events_with(processor) .build(); // 通过`Producer`句柄将单个事件发布到Disruptor中。 for i in 0..10 { producer.publish(|e| { e.price = i as f64; }); } // 将一批事件发布到Disruptor中。 producer.batch_publish(5, |iter| { for e in iter { // `iter`保证会产生5个事件。 e.price = 42.0; } }); }// 在此处,Producer实例超出作用域,当处理器完成处理所有事件后, // Disruptor也会被释放。
该库还支持将线程固定在核心上,以避免上下文切换引起的延迟。 一个更高级的用法,演示了这一点以及多个生产者和多个相互依赖的消费者,可能如下所示:
use disruptor::*; use std::thread; struct Event { price: f64 } fn main() { let factory = || { Event { price: 0.0 }}; // 用于处理事件的闭包。 let h1 = |e: &Event, sequence: Sequence, end_of_batch: bool| { // 在这里添加处理逻辑。 }; let h2 = |e: &Event, sequence: Sequence, end_of_batch: bool| { // 在这里添加一些处理逻辑。 }; let h3 = |e: &Event, sequence: Sequence, end_of_batch: bool| { // 在这里添加更多处理逻辑。 }; let mut producer1 = disruptor::build_multi_producer(64, factory, BusySpin) // `h2`与`h1`并发处理事件。 .pin_at_core(1).handle_events_with(h1) .pin_at_core(2).handle_events_with(h2) .and_then() // `h3`在`h1`和`h2`之后处理事件。 .pin_at_core(3).handle_events_with(h3) .build(); // 创建另一个生产者。 let mut producer2 = producer1.clone(); // 发布到Disruptor。 thread::scope(|s| { s.spawn(move || { for i in 0..10 { producer1.publish(|e| { e.price = i as f64; }); } }); s.spawn(move || { for i in 10..20 { producer2.publish(|e| { e.price = i as f64; }); } }); }); }// 在此处,Producer实例超出作用域,当处理器完成处理所有事件后, // Disruptor也会被释放。
如果你需要在处理器线程中存储一些既不是Send也不是Sync的状态,例如Rc<RefCell<i32>>,那么你可以创建一个用于初始化该状态的闭包,并在构建Disruptor时将其与处理闭包一起传递。然后Disruptor将在每个事件上传递一个指向你的状态的可变引用。例如:
use std::{cell::RefCell, rc::Rc}; use disruptor::*; struct Event { price: f64 } #[derive(Default)] struct State { data: Rc<RefCell<i32>> } fn main() { let factory = || { Event { price: 0.0 }}; let initial_state = || { State::default() }; // 用于处理事件*和*状态的闭包。 let processor = |s: &mut State, e: &Event, _: Sequence, _: bool| { // 修改你的自定义状态: *s.data.borrow_mut() += 1; }; let size = 64; let mut producer = disruptor::build_single_producer(size, factory, BusySpin) .handle_events_and_state_with(processor, initial_state) .build(); for i in 0..10 { producer.publish(|e| { e.price = i as f64; }); } }
该库中的一切都是关于低延迟的,这极大地影响了该库中的所有选择。 例如,你不能分配一个事件并将其移动到环形缓冲区中。相反,事件在启动时就被分配,以确保它们在内存中共同定位,从而提高缓存一致性。 然而,你仍然可以在堆上分配一个结构体,并将其所有权移动到环形缓冲区上的事件字段中。 只要你意识到这可能会增加延迟,因为结构体是由一个线程分配而由另一个线程释放的。 因此,在分配器中会发生同步。
也没有使用动态分发 - 一切都是单态的。
这个库需要使用Unsafe来实现低延迟。 虽然不能保证没有错误,但已经使用了以下方法来消除错误:
verification/文件夹)。SPSC和MPSC Disruptor变体已经进行了基准测试,并与Crossbeam进行了比较。请参见benches/spsc.rs和benches/mpsc.rs文件中的代码。
以下是在 2016 年的 MacBook Pro(配备 2.6 GHz 四核 Intel Core i7 处理器)上运行 SPSC 基准测试的结果。在现代 Intel Xeon 处理器上,这些数字应该会更好。此外,在 Mac 上无法隔离核心并固定线程,这本可以产生更稳定的结果。这是未来的工作。
如果您有任何改进基准测试的建议,请随时提出问题。
为了提供一个相对真实的基准测试,不仅考虑了不同大小的突发,还考虑了突发之间的不同暂停时间:0 毫秒、1 毫秒和 10 毫秒。
以下延迟是每个元素的平均延迟,置信区间为 95%(标准 criterion 设置)。捕获所有延迟并计算各种百分位数(特别是最大延迟)是未来的工作。然而,我预计下面的测量结果能代表您在实际应用中可以达到的性能。
延迟:
| 突发大小 | Crossbeam | Disruptor | 改进 |
|---|---|---|---|
| 1 | 65 ns | 32 ns | 51% |
| 10 | 68 ns | 9 ns | 87% |
| 100 | 29 ns | 8 ns | 72% |
吞吐量:
| 突发大小 | Crossbeam | Disruptor | 改进 |
|---|---|---|---|
| 1 | 15.2M / s | 31.7M / s | 109% |
| 10 | 14.5M / s | 117.3M / s | 709% |
| 100 | 34.3M / s | 119.7M / s | 249% |
延迟:
| 突发大小 | Crossbeam | Disruptor | 改进 |
|---|---|---|---|
| 1 | 63 ns | 33 ns | 48% |
| 10 | 67 ns | 8 ns | 88% |
| 100 | 30 ns | 9 ns | 70% |
吞吐量:
| 突发大小 | Crossbeam | Disruptor | 改进 |
|---|---|---|---|
| 1 | 15.9M / s | 30.7M / s | 93% |
| 10 | 14.9M / s | 117.7M / s | 690% |
| 100 | 33.8M / s | 105.0M / s | 211% |
延迟:
| 突发大小 | Crossbeam | Disruptor | 改进 |
|---|---|---|---|
| 1 | 51 ns | 32 ns | 37% |
| 10 | 67 ns | 9 ns | 87% |
| 100 | 30 ns | 10 ns | 67% |
吞吐量:
| 突发大小 | Crossbeam | Disruptor | 改进 |
|---|---|---|---|
| 1 | 19.5M / s | 31.6M / s | 62% |
| 10 | 14.9M / s | 114.5M / s | 668% |
| 100 | 33.6M / s | 105.0M / s | 213% |
Disruptor 和 Crossbeam 库之间显然存在差异。然而,这并不是因为 Crossbeam 库不是一个优秀的软件。事实上它很优秀。Disruptor 通过牺牲 CPU 和内存资源来换取更低的延迟和更高的吞吐量,这就是它能够达到这些结果的原因。如基准测试中 10 和 100 个事件的突发所示,Disruptor 在发布事件批次时表现更为出色。
随着突发大小的增加,两个库的性能都有很大提升,但 Disruptor 的性能对突发之间的暂停更具韧性,这也是其设计目标之一。
有多个其他 Rust 项目模仿了 LMAX Disruptor 库:
该库支持的一个关键特性是来自不同线程的多个生产者,而上述库都不支持这一特性(在撰写本文时)。
欢迎您创建拉取请求或提出问题,提出改进建议。
我将全权决定是否接受更改,并将重点关注这些更改是否适合本 crate 的目的和设计。
空白!所有项目都已实现。


职场AI,就用扣子
AI办公助手,复杂任务高效处理。办公效率低?扣子空间AI助手支持播客生成、PPT制作、网页开发及报告写作,覆盖科研、商业、舆情等领域的专家Agent 7x24小时响应,生活工作无缝切换,提升50%效率!


多风格AI绘画神器
堆友平台由阿里巴巴设计团队创建,作为一款AI驱动的设计工具,专为设计师提供一站式增长服务。功能覆盖海量3D素材、AI绘画、实时渲染以及专业抠图,显著提升设计品质和效率。平台不仅提供工具,还是一个促进创意交流和个人发展的空间,界面友好,适合所有级别的设计师和创意工作者。


零代码AI应用开发平台
零代码AI应用开发平台,用户只需一句话简单描述需求,AI能自动生成小程序、APP或H5网页应用,无需编写代码。


免费创建高清无水印Sora视频
Vora是一个免费创建高清无水印Sora视频的AI工具


最适合小白的AI自动化工作流平台
无需编码,轻松生成可复用、可变现的AI自动化工作流

大模型驱动的Excel数据处理工具
基于大模型交互的表格处理系统,允许用户通过对话方式完成数据整理和可视化分析。系统采用机器学习算法解析用户指令,自动执行排序、公式计算和数据透视等操作,支持多种文件格式导入导出。数据处理响应速度保持在0.8秒以内,支持超过100万行数据的即时分析。


AI辅助编程,代码自动修复
Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。


AI论文写作指导平台
AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。


AI一键生成PPT,就用博思AIPPT!
博思AIPPT,新一代的AI生成PPT平台,支持智能生成PPT、AI美化PPT、文本&链接生成PPT、导入Word/PDF/Markdown文档生成PPT等,内置海量精美PPT模板,涵盖商务、教育、科技等不同风格,同时针对每个页面提供多种版式,一键自适应切换,完美适配各种办公场景。


AI赋能电商视觉革命,一站式智能商拍平台
潮际好麦深耕服装行业,是国内AI试衣效果最好的软件。使用先进AIGC能力为电商卖家批量提供优质的、低成本的商拍图。合作品牌有Shein、Lazada、安踏、百丽等65个国内外头部品牌,以及国内10万+淘宝、天猫、京东等主流平台的品牌商家,为卖家节省将近85%的出图成本,提升约3倍出图效率,让品牌能够快速上架。
最新AI工具、AI资讯
独家AI资源、AI项目落地

微信扫一扫关注公众号