-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fallback to Parking in std::sync::mpsc
Channels
#125204
Conversation
This comment has been minimized.
This comment has been minimized.
63a6e25
to
23fb55f
Compare
// Because writes to the channel are also sequentially consistent, | ||
// this creates a total order between storing a value and registering a waiter. | ||
let state = self.state.load(Ordering::SeqCst); | ||
|
||
// If a notification is already set, the waker thread will take care | ||
// of further notifications. Otherwise we have to notify if there are waiters. | ||
if (state >> WAKER) > 0 && (state & NOTIFIED == 0) { | ||
return self |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
given the fetch_update() is likely to be a a compare_exchange_weak loop already, could it go straight into it instead of doing this extra load check before it?
/// on the channel, as well as creates a chain that makes up for lost wakeups, | ||
/// allowing threads to park even if the channel is in an inconsistent state. | ||
struct WakerState { | ||
state: AtomicU64, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thoughts on making this an AtomicUsize for 32bit platforms?
Closing this until the PR on the crossbeam-channel side is merged. |
Currently, the queues used by the
mpsc
channel flavors are not lock-free. The linearization point of a send or receive is moving the tail or head index respectively, meaning that senders and receivers must spin if they see an updated head/tail despite the corresponding value not being written yet. Blocking in such a case is not possible as sends might notify a receiver even though they are not yet visible due to a lagging sender holding up the channel, or vice versa, leading to missed wakeups.The current solution of unbounded spinning can lead to issues, especially on platforms with a single core or custom thread priorities. One way to allow falling back to blocking is if waiters that see more values in the channel after being woken up notify any other waiters, making up for any missed notifications. However, this ends up being quite expensive and can lead to many unnecessary wakeups. The solution implemented by this PR is wakeup throttling, as used by tokio and other userspace schedulers. The new algorithm is in
sync/mpmc/waker.rs
.Should resolve #114851 and #112723. An alternative solution is to introduce a non-linearizable version of
try_recv
, but fixing the unbounded spinning is important regardless. This PR leaves a couple cases of unbounded spinning when discarding the messages in the unbounded channel that can be addressed in a later PR, those should not be a large concern.There are a couple other cosmetic changes included in this PR that were not previously ported from crossbeam. Hopefully they shouldn't distract from the primary changes. Downstream patch: crossbeam-rs/crossbeam#1105.
r? @Amanieu