perf: stop idle server promptly on should_exit

Closed
RA
8h ago
+45-5

Fixes #3216

Motivation and Context

When embedding Uvicorn in isolated test runners or programmatic environments, an idle server took ~202 ms to stop from setting server.should_exit = True until server.serve() returned, even with no active connections and lifespan disabled.

This was caused by two fixed delays in Server:

  1. main_loop polled on_tick() with an unconditional await asyncio.sleep(0.1).
  2. shutdown() unconditionally slept another 100 ms (await asyncio.sleep(0.1)) after iterating connections, even when self.server_state.connections was empty.

Solution

  1. Wakeable Event on should_exit:
    • Manage _exit_event = asyncio.Event().
    • Expose should_exit as a property with getter/setter; setting server.should_exit = True immediately wakes up the asyncio.wait_for(self._exit_event.wait(), timeout=0.1) in main_loop.
  2. Conditional Connection Drain:
    • Only sleep the 100 ms grace period in shutdown() if active connections exist in self.server_state.connections.
  3. Tests:
    • Added test_idle_server_fast_shutdown in tests/test_server.py.
    • Verified idle server stop latency drops from ~216 ms down to <1 ms (<0.3 ms in local test runs).

Signed-off-by: Raj Gahoi gahoiraj01@gmail.com