-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
This issue is about analyzing the DedicatedThreadScheduler to discuss about how it could be improved.
Summary of the actual implementation
The scheduler is implemented by a background thread and a ConcurrentQueue. The ConcurrentQueue is used as a message queue to send the scheduled work items to the scheduler's background thread.
The background thread is a while loop that:
- reads item from the message queue, add them in a List
allWork
- iterate all work items in
allWork
to invoke the expired items - sleep (defined by akka.scheduler.tick-duration)
Dedicated Thread vs Timer
If there are only a few instances of the scheduler, I think that the dedicated thread is the good approach. I don't see why you would need to have more than one in a process.
allWork
data structure
The List is fairly inefficient since the scheduler has to iterate all work items every time. A heap structure should be a good match for this, it would be sorted by clock time and the scheduler would only have to check the head. The time complexity of the heap would be O(log n) for push and O(log n) for pop compared to O(1) for push and O(n) for pop for the List.
The optimal structure I can think of is a circular list of buckets with a resolution defined by tick-duration. The work items would be inserted in their appropriate bucket, push and pop to that structure would both be O(1). (To limit the size of the circular list, it should have one list with tick-duration
resolution and another with a bigger resolution (e.g. 1 second))
Thread.Sleep vs Wake-up signals
With the current implementation, the thread wakes up every tick-duration
to check if a work item expired. Depending on the work load, the scheduler could waste cpu cycles by waking up often when there is no expired work items.
Something like an AutoResetEvent could be used to wake up the thread only when it has actual work to do.
Execution of expired work items
With the current implementation, the work items are executed inside the scheduler's thread. This could potentially delay the execution of other work items. I think it should push the execution on the .Net ThreadPool and have an optional setting to execute a specific work item synchronously.
End note
Of course all this talk is theoretical, we should create a benchmark that mimics the expected work load in Akka.Net and try the various proposals.