-
Notifications
You must be signed in to change notification settings - Fork 230
Wait Strategies
Each Disruptor has a single wait strategy (IWaitStrategy) that is responsible for notifying processors of new events. The wait strategy creates sequence waiters (ISequenceWaiter) which are used by event processors to wait for event sequences.
Wait strategy | Description | Note |
---|---|---|
BlockingWaitStrategy |
Uses Monitor.Wait and Monitor.Pulse to notify of new events and then busy spins to wait for dependent sequences. |
This is the default wait strategy. |
BlockingSpinWaitWaitStrategy |
Uses Monitor.Wait and Monitor.Pulse to notify of new events and then uses System.Threading.SpinWait to wait for dependent sequences. |
This strategy should not generate high CPU usage. |
BusySpinWaitStrategy |
Busy spins to wait for new events and dependent sequences. | |
SleepingWaitStrategy |
Uses a mix of Thread.Yield and Thread.Sleep(0) to wait for new events and dependent sequences. |
|
YieldingWaitStrategy |
Uses Thread.Yield to wait for new events and dependent sequences. |
|
SpinWaitWaitStrategy |
Uses System.Threading.SpinWait to wait for new events and dependent sequences. |
This strategy should not generate high CPU usage. |
Please note that the wait strategy is both responsible for notifying about new events and for waiting until dependent sequences are available, i.e., that previous event handlers have processed the event. The API allows signalling of new events, but not signalling of sequence availability. Thus all wait strategies, even blocking ones, must rely on variations of spin waiting to wait for sequence availability. This spin waiting can generate high CPU usage, which is a common source of issues reported by users..
A few wait strategies use System.Threading.SpinWait
. This synchronization type is implemented using a mix of Thread.SpinWait
, Thread.Yield
, Thread.Sleep(0)
and Thread.Sleep(1)
. On Windows, the thread pause duration cannot be less than the system timer resolution, which is 15.6 ms by default. So a call to Thread.Sleep(1)
can generate pauses of 15.6 ms. To avoid this issue, the Disruptor often uses its own synchronization type, AggressiveSpinWait, which does not call Thread.Sleep(1)
.
The wait strategy API evolved over time and it is now very different from the original Java version.
Here is the list of changes:
- [V5] Use
CancellationToken
instead ofISequenceBarrier
to notify shutdown.- Passing the sequencer barrier to wait strategies was slightly dangerous because the sequence barrier also exposed methods like
Alert
orClearAlert
. -
CancellationToken
is safer, more explicit, and more idiomatic for .NET.
- Passing the sequencer barrier to wait strategies was slightly dangerous because the sequence barrier also exposed methods like
- [V5] Return a dedicated type
SequenceWaitResult
inWaitFor
.- This type makes explicit that wait strategies can timeout.
- This type avoids the previous exception-based design.
- [V5] Use
DependentSequenceGroup
instead of the sequence coupleSequence cursor, ISequence dependentSequence
.- This change makes the API more explicit, avoids exposing mutable sequences to wait strategies and slightly improves performance.
- [V7] Extract
ISequenceWaiter
fromIWaitStrategy
- The wait strategy is now a factory of
ISequenceWaiter
. - The wait strategy can now more easily store dedicated state per waiter.
- The wait strategy is now a factory of
- [V7] Use a dedicated type to identify sequencer waiter owners:
SequenceWaiterOwner
- The wait strategy can more easily identify the event handlers and apply custom logic per waiter.