This is something I built for my own use, as a reference I can use to remember some of the properties of the Rust channel implementations I use most often.
Which channels implement fallible send? Which one implements an async sender and blocking receiver? What do I lose if I make my channel bounded size? These are the questions I ask myself when picking out an mpsc channel implementation.
Do I care about performance? Yes. But I generally assume that all of these channels are in use in a lot of environments, and have been benchmarked a hundred ways, and generally have pretty good performance and mostly lock-free operation (except possibly when resizing unbounded channels).
Sending §
growing | blocking | fallible | async | |
---|---|---|---|---|
std sync_channel | ✘ | send | try_send | ✘ |
std channel | send | ✘ | ✘ | ✘ |
tokio channel | ✘ | blocking_send | try_send | send |
tokio unbounded_channel | send | ✘ | ✘ | ✘ |
crossbeam bounded | ✘ | send | try_send | ✘ |
crossbeam unbounded | send | ✘ 1 | try_send | ✘ |
Receiving §
blocking | fallible | async | clone | |
---|---|---|---|---|
std sync_channel | recv | try_recv | ✘ | no |
std channel | recv | try_recv | ✘ | no |
tokio channel | blocking_recv | try_recv | recv | no |
tokio unbounded_channel | blocking_recv | try_recv | recv | no |
crossbeam bounded | recv | try_recv | ✘ | yes 2 |
crossbeam unbounded | recv | try_recv | ✘ | yes 2 |
Notes:
crossbeam unbounded()
returns the same Sender
type as bounded()
; that Sender::send
is documented as "blocks the thread until..." so while I think the unbounded send will never block, that documentation is a bit unclear.
I'm not certain that being able to clone
a crossbeam
Receiver
makes the channel a true MPMC channel, but it's a useful property nonetheless.
I've only considered mpsc channels, not broadcast, oneshot, watch, or other channel variants. These can be interesting and useful, but are out of scope for this table.
I also haven't considered implementations that aren't lock-free in the hot path. Implementations that are a Mutex<VecDeque<T>>
in a trenchcoat may have acceptable performance for some workloads, but they are not directly comparable to the data structures in this table.
Cheers! Good luck with your Rust projects.