#reader #reader-writer #rcu #values #old #read #multiple-values

已删除 local-rcu

具有安全API和本地旧值收集的RCU

3个稳定版本

1.0.4 2023年11月2日
1.0.3 2023年11月1日
1.0.1 2023年10月29日

#15 in #rcu

每月下载量27次

OSL-3.0 许可证

22KB
168

local-rcu

local-rcu 提供类似于RCU的并发原语,优化读取并延迟返回旧值(即:用于丢弃/释放)。它提供一个写入者、多个读取者的数据结构。

读取者不会阻塞写入者,慢速读取者只会导致更多内存使用(假设有持续更新的写入者,旧值会保留,直到没有读取者检查它们)。

如果我想实现类似X的行为,我应该怎么做?

左-右

  1. 在每次调用 local_rcu::Writer::sync() 之前调用 local_rcu::Writer::write()
  2. 修改 local_rcu::Writer::sync() 返回的旧值(即:执行自己的 Absorb)并将其传递给 Writer::write() 调用。

注意: Writer::new() 只接受1个初始值,而 Writer::write() 将尝试返回旧值,如果可能的话。这意味着将需要额外的代码来跟踪您将要更新的“备用”值。

tokio::sync::watch

  1. event-listenerlocal_rcu::Writer 配对
  2. 每个读取者监听 event-listener 上的事件,以知道进行另一次读取。
  3. 在用 local_rcu::Writer::write() 写入新值后,让作者发出 event-listener 信号。

替代方案

local-rcu 相比...

  • triple_buffer:使用原子交换。允许立即释放/重用数据。单消费者。
  • std::sync::mpsc::channel:MPSC(与SPMC相对),可读取多个值(不仅仅是最新值)
  • left-right:使用单个“旧”值而不是任意数量的旧值。慢速读者可以阻止发布新值。它需要实现“吸收”的概念,将“旧”值的修改放入 left-right 内部。使用“操作日志”以便作者不会直接阻塞读者(只有发布会被阻塞)。
  • tokio::sync::watch:允许通过异步通知更新,使用互斥锁来控制对值的访问。读者阻塞作者。
  • tokio::sync::broadcast:支持多个生产者,提供一些“历史”值(而不是只有最新值),支持异步等待新值,内部使用互斥锁。

与其他 Rust “rcu” 仓库相比

local-rcu 相比...

  • crossbeam-epoch。使用全局共享的垃圾回收队列。有一个单独的 Guard 概念(类似于 rcu_clean::graceful),通过延迟垃圾回收来降低读取成本。包括基于 miri 的验证(以及 loom
  • rcu-clean。不包括任何使用 loom 或其他检查工具的测试。提供多种释放旧值的机制(“graceful”:一个基于全局 Arc 的独立方法,“arcrcu”:每个值的自定义 Arc-like,“boxrcu” & “rccru” 之间不可共享)。允许线程间共享的方法都需要增加/减少引用计数的机制。“graceful”通过延迟释放旧数据来延迟原子引用计数的增加/减少(降低读取成本),不返回旧值给调用者。在“graceful”变体中,作者可以短暂阻塞想要创建新“Grace”的读者,而更新正在进行。在“arcrcu”中,读者不会被作者阻塞。内部使用自定义单链表排队旧值以进行释放。在“arcrc”中,必须手动调用 clean(),不存在自动清理。
  • rcu_cell。缺少大部分文档。使用原子比较和交换。读者阻塞写者(简而言之,在引用递增之前,值指针中的一个位被用作锁)。允许多个写者(使用比较和交换确定哪个写者被发布)。包含一个自定义的类似于ARC的引用计数接口,该接口使用原子加法和减法。每个写入的值都包括与值相邻的引用计数。每次读取都会对引用计数进行递增和递减。不包括使用 loom 或其他检查工具进行的任何测试。"锁定"数据以供读取是通过读者通过比较交换在指针中设置一个位来完成的。换句话说:所有读者和写者都在一个共享位置上执行比较交换,这可能导致对包含指针的缓存行的竞争。
  • atom_box。使用危险指针而不是RCU。
  • urcu.
  • srcu
  • keepcalm

依赖项

~0–25MB
~337K SLoC