@@ -162,6 +162,10 @@ cdef class Loop:
162162 self ._recv_buffer_in_use = 0
163163
164164 err = uv.uv_loop_init(self .uvloop)
165+ if err < 0 :
166+ raise convert_error(err)
167+
168+ err = uv.uv_loop_configure(self .uvloop, uv.UV_METRICS_IDLE_TIME)
165169 if err < 0 :
166170 raise convert_error(err)
167171 self .uvloop.data = < void * > self
@@ -527,6 +531,7 @@ cdef class Loop:
527531
528532 self ._thread_id = PyThread_get_thread_ident()
529533 self ._running = 1
534+ self ._loop_start_time = self ._time()
530535
531536 self .handler_check__exec_writes.start()
532537 self .handler_idle.start()
@@ -628,6 +633,10 @@ cdef class Loop:
628633 self ._default_executor = None
629634 executor.shutdown(wait = False )
630635
636+ cdef uint64_t _event_loop_idle_time(self ):
637+ """ Returns number of nanoseconds the loop has been idle"""
638+ return uv.uv_metrics_idle_time(self .uvloop)
639+
631640 cdef uint64_t _time(self ):
632641 # asyncio doesn't have a time cache, neither should uvloop.
633642 uv.uv_update_time(self .uvloop) # void
@@ -1337,6 +1346,24 @@ cdef class Loop:
13371346 return self .call_later(
13381347 when - self .time(), callback, * args, context = context)
13391348
1349+ def _event_loop_utilization (self ):
1350+ """ Returns idle and active time in milliseconds and the percentage of
1351+ time the event loop is active
1352+ """
1353+
1354+ idle = 0.
1355+ active = 0.
1356+ utilization = 0.
1357+
1358+ if not self ._running:
1359+ return idle, active, utilization
1360+
1361+ idle = self ._event_loop_idle_time() / 10 ** 6
1362+ active = self ._time() - self ._loop_start_time - idle
1363+ utilization = active / (active + idle)
1364+
1365+ return idle, active, utilization
1366+
13401367 def time (self ):
13411368 """ Return the time according to the event loop's clock.
13421369
0 commit comments