3 个版本
0.1.2 | 2022 年 3 月 20 日 |
---|---|
0.1.1 | 2022 年 3 月 20 日 |
0.1.0 | 2022 年 3 月 19 日 |
#716 in 并发
17KB
336 行
cupchan
是的,cup-chan,请帮我交换杯子 uwu
两个线程之间简单的异步覆盖通道,通过交换杯子实现无需等待和阻塞
这个项目源于我需要在一个线程上懒更新另一个线程上的数据,而不必等待互斥锁。
工作原理
这个 crate 通过三个可交换标签的“杯子”来实现无等待和阻塞的通道。每个杯子都标记为具有特定的目的,即写入、存储和读取。(此标记存储在原子 u8 中)。
写入线程可以访问写入杯子,读取线程可以访问标记为读取的杯子。一旦写入线程准备好更新读取线程,它就会向自己的杯子写入并调用 flush()
,该操作会切换写入和存储标记。(这是一个使用 fetch_update
的单个原子操作)。
例如,杯子可能开始如下所示:<W><S><R>
写入线程写入一些内容:<S><W><R>
- 写入标记已与存储标记交换,并设置了一个标志来告知读取线程存储已被更新。
读取线程想要检查数据,因此它会检查更新标志。如果已设置,则读取线程将存储和读取标记交换。然后读取线程检查读取杯子中的数据。
标记系统确保写入和读取线程永远不会同时访问同一个杯子。
以下是所有可能的杯子状态及其之间关系的图表: quiver.
测试
此crate已通过loom验证。
运行测试
$ cargo test
$ RUSTFLAGS="--cfg loom" cargo test --test loom_test --release
备注:如果使用LOOM标志,在更改代码后请确保清除检查点文件。
基准测试
每个基准测试代表发送了5_000个64位整数。
test tests::bench_crossbeam_chan_cap_10 ... bench: 227,330 ns/iter (+/- 53,862)
test tests::bench_crossbeam_chan_cap_3 ... bench: 406,431 ns/iter (+/- 73,856)
test tests::bench_cupchan_greedy ... bench: 404,699 ns/iter (+/- 36,296)
test tests::bench_cupchan_lazy ... bench: 102,177 ns/iter (+/- 10,770)
test tests::bench_flume_chan ... bench: 725,894 ns/iter (+/- 107,237)
此crate在其预期功能(懒加载地流式传输更新值)上比crossbeam和flume更快。如果您只需要尽可能快地移动和消耗数据,请使用这些crate。
(懒加载与贪婪的区别在于懒加载在每次读取后都会释放线程)。
它仍然没有达到应有的速度,主要因为使用了fetch_update
而不是CPU内嵌函数。如果有人有改进此处的想法,请在rust discord上联系我(ID为@Zyansheep#8020
)。
依赖项
~0–26MB
~334K SLoC