Class: Async::Idler
- Inherits:
-
Object
- Object
- Async::Idler
- Defined in:
- lib/async/idler.rb
Overview
A load balancing mechanism that can be used process work when the system is idle.
Instance Method Summary collapse
-
#async(*arguments, parent: (@parent or Task.current), **options, &block) ⇒ Object
Wait until the system is idle, then execute the given block in a new task.
-
#initialize(maximum_load = 0.8, backoff: 0.001, parent: nil) ⇒ Idler
constructor
Create a new idler.
-
#wait ⇒ Object
Wait until the system is idle, according to the maximum load specified.
Constructor Details
#initialize(maximum_load = 0.8, backoff: 0.001, parent: nil) ⇒ Idler
Create a new idler.
16 17 18 19 20 21 22 23 |
# File 'lib/async/idler.rb', line 16 def initialize(maximum_load = 0.8, backoff: 0.001, parent: nil) @maximum_load = maximum_load @backoff = backoff @current = backoff @parent = parent @mutex = Mutex.new end |
Instance Method Details
#async(*arguments, parent: (@parent or Task.current), **options, &block) ⇒ Object
Wait until the system is idle, then execute the given block in a new task.
33 34 35 36 37 38 |
# File 'lib/async/idler.rb', line 33 def async(*arguments, parent: (@parent or Task.current), **, &block) wait # It is crucial that we optimistically execute the child task, so that we prevent a tight loop invoking this method from consuming all available resources. parent.async(*arguments, **, &block) end |
#wait ⇒ Object
Wait until the system is idle, according to the maximum load specified.
If the scheduler is overloaded, this method will sleep for an exponentially increasing amount of time.
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/async/idler.rb', line 43 def wait @mutex.synchronize do scheduler = Fiber.scheduler while true load = scheduler.load if load <= @maximum_load # Even though load is okay, if @current is high, we were recently overloaded. Sleep proportionally to prevent burst after load drop: if @current > @backoff # Sleep a fraction of @current to rate limit: sleep(@current - @backoff) # Decay @current gently towards @backoff: alpha = 0.99 @current *= alpha + (1.0 - alpha) * (load / @maximum_load) end break else # We're overloaded, so increase backoff: @current *= (load / @maximum_load) sleep(@current) end end end end |