Rust in Everything
基于 crossbeam 0.8.5

crossbeam 源码解析

全卷只对着一个发布提交写:

crate版本tagcommit日期
crossbeam、crossbeam-channel、crossbeam-deque、crossbeam-epoch、crossbeam-utils、crossbeam-queue0.8.5、0.5.17、0.8.8、0.9.21、0.8.23、0.3.14各 crate 自己的 tag,如 crossbeam-channel-0.5.172920c984(v0.8 发布分支)2026-09-06
crossbeam-skiplist0.1.3crossbeam-skiplist-0.1.33aa2598e(main)2024-01-08

crossbeam 是 Rust 的并发工具箱。它不是运行时,也不是线程池,而是几块互相独立、可以单独依赖的积木:缓存行填充 CachePadded、退避 Backoff、任意类型的原子单元 AtomicCell、基于纪元的内存回收(EBR)、Chase-Lev 工作窃取双端队列、MPMC channel 和 select!、无锁队列 ArrayQueue / SegQueue、并发跳表。它的一部分后来进了标准库:Rust 1.63 的 std::thread::scope,以及 1.67.0 起 std::sync::mpsc 的现行实现,就是从 crossbeam-channel 移植的。另一部分至今只在这里:rayon 的调度器建在它的 deque 上。

它和前几卷的关系:tokio 卷讲的是一个 async 运行时,本卷讲的是线程和原子变量这一层,没有 Future。tokio 没有依赖 crossbeam,但它的缓存行对齐取值注明抄自 crossbeam,它 2019 年以前的本地队列就是 crossbeam 的 deque;tantivy、pingora、sqlx、tauri 各卷都直接用到 crossbeam 的 channel 或队列。本卷之后是 rayon 卷。

全卷沿四条线展开:

  • 一条消息:bounded(1) 上 send 判满、Backoff 自旋、注册到 SyncWaker、park;recv 改写槽的 stamp、notify、CAS 选中等待者、unpark。
  • 一个任务:Worker::push 写进环形缓冲、满了加倍;Stealer::steal 读 front、pin、读 back、读任务、CAS;旧缓冲交给 epoch。
  • 一块内存的回收:epoch::pin 写本地纪元、SeqCst fence;defer_destroy 进本地袋子、封上全局纪元进全局队列;所有已 pin 的参与者都跟上时纪元推进,落后两个纪元的袋子被回收。
  • 内存序横线:每遇到一个 Ordering,问它在和谁配对、防的是哪种重排。
flowchart TB
  intro[00 导读] --> overview[01 全景]
  overview --> mo[02 内存序与验证]
  mo --> utils[03 utils]
  utils --> epoch[04 epoch]
  epoch --> deque[05 deque]
  utils --> chan[06 channel]
  chan --> qs[07 queue 与 skiplist]
  epoch --> qs
  deque --> design[08 设计取舍]
  qs --> design
  design --> pit[09 常见坑]
  pit --> site[10 在本站中]
  site --> hands[11 动手]

实验环境

本机 Apple M2 Max(8 个性能核 + 4 个能效核,缓存行 128 字节),macOS,rustc 1.99.1。实验程序在 exp-crossbeam/ 下,依赖锁定在上表的版本,对照组是 std、flume、parking_lot、tokio。性能类一律 release、至少重复 3 次取中位数,注明测量时的负载;macOS 不能绑核,线程可能被调度到能效核上。每个实验都带一个反向验证。规矩的细节见 怎么读这一卷。

各部分

  1. 00 导读:版本与分支、四条主线、阅读路线、实验方法;crate 分层、feature 与 cfg。
  2. 01 全景:crossbeam 补了 std 的哪些空白;三条主线各走一遍。
  3. 02 内存序与验证:五类 Ordering 用法;loom、Miri、TSan 和为它们多出来的 cfg。
  4. 03 crossbeam-utils:CachePadded、Backoff、AtomicCell、Parker 与 WaitGroup、ShardedLock、作用域线程。
  5. 04 crossbeam-epoch:本卷重点。为什么需要内存回收;指针类型、pin、defer、回收;内部的无锁链表和队列。
  6. 05 crossbeam-deque:Chase-Lev、扩容与回收、Steal::Retry 与批量窃取、Injector。rayon 卷的前置。
  7. 06 crossbeam-channel:本卷重点。六种 flavor、Context 与 Waker、select;和 std::sync::mpmc 逐文件对照,和 tokio mpsc、flume 对照。
  8. 07 queue 与 skiplist:ArrayQueue、SegQueue;并发跳表。
  9. 08 设计取舍:把各章的取舍汇总到一起。
  10. 09 常见坑:用报错原文或现象做标题。
  11. 10 在本站中:本站经 tantivy、rayon、sqlx、pingora 间接依赖的 crossbeam(desktop 构建还经 tao)。
  12. 11 动手:最小 MPMC channel、最小 EBR。

从「导读」开始。只想用好 crossbeam 的读者,读 01、06、09;为 rayon 卷做准备的,读 03、04、05;想读懂实现的,按顺序读。

💬 关联讨论

发起讨论
加载中...