lib/async/scheduler.rb in async-2.8.2 vs lib/async/scheduler.rb in async-2.9.0
- old
+ new
@@ -35,13 +35,37 @@
@selector = selector || ::IO::Event::Selector.new(Fiber.current)
@interrupted = false
@blocked = 0
+ @busy_time = 0.0
+ @idle_time = 0.0
+
@timers = ::Timers::Group.new
end
+ # Compute the scheduler load according to the busy and idle times that are updated by the run loop.
+ # @returns [Float] The load of the scheduler. 0.0 means no load, 1.0 means fully loaded or over-loaded.
+ def load
+ total_time = @busy_time + @idle_time
+
+ # If the total time is zero, then the load is zero:
+ return 0.0 if total_time.zero?
+
+ # We normalize to a 1 second window:
+ if total_time > 1.0
+ ratio = 1.0 / total_time
+ @busy_time *= ratio
+ @idle_time *= ratio
+
+ # We don't need to divide here as we've already normalised it to a 1s window:
+ return @busy_time
+ else
+ return @busy_time / total_time
+ end
+ end
+
def scheduler_close
# If the execution context (thread) was handling an exception, we want to exit as quickly as possible:
unless $!
self.run
end
@@ -265,10 +289,12 @@
# When terminating the event loop, we already know we are finished. So we don't need to check the task tree. This is a logical requirement because `run_once` ignores transient tasks. For example, a single top level transient task is not enough to keep the reactor running, but during termination we must still process it in order to terminate child tasks.
#
# @parameter timeout [Float | Nil] The maximum timeout, or if nil, indefinite.
# @returns [Boolean] Whether there is more work to do.
private def run_once!(timeout = 0)
+ start_time = Async::Clock.now
+
interval = @timers.wait_interval
# If there is no interval to wait (thus no timers), and no tasks, we could be done:
if interval.nil?
# Allow the user to specify a maximum interval if we would otherwise be sleeping indefinitely:
@@ -285,9 +311,18 @@
rescue Errno::EINTR
# Ignore.
end
@timers.fire
+
+ # Compute load:
+ end_time = Async::Clock.now
+ total_duration = end_time - start_time
+ idle_duration = @selector.idle_duration
+ busy_duration = total_duration - idle_duration
+
+ @busy_time += busy_duration
+ @idle_time += idle_duration
# The reactor still has work to do:
return true
end